用户可以用自定义的异常处理类来扩展 PHP 内置的异常处理类。以下的代码说明了在内置的异常处理类中,哪些属性和方法在子类中是可访问和可继承的。译者注:以下这段代码只为说明内置异常处理类的结构,它并不是一段有实际意义的可用代码。
<code><?php <br />class Exception{<br>protected $message = 'Unknown exception'; // 异常信息<br>protected $code = 0; // 用户自定义异常代码<br>protected $file; // 发生异常的文件名<br>protected $line; // 发生异常的代码行号<br>function __construct($message = null, $code = 0);<br>final function getMessage(); // 返回异常信息<br>final function getCode(); // 返回异常代码<br>final function getFile(); // 返回发生异常的文件名<br>final function getLine(); // 返回发生异常的代码行号<br>final function getTrace(); // backtrace() 数组<br>final function getTraceAsString(); // 已格成化成字符串的 getTrace() 信息<br>/* 可重载的方法 */<br>function __toString(); // 可输出的字符串<br>}<br>?>如果使用自定义的类来扩展内置异常处理类,并且要重新定义构造函数的话,建议同时调用 parent::__construct()来检查所有的变量是否已被赋值。当对象要输出字符串的时候,可以重载 __toString() 并自定义输出的样式。
扩展 PHP 内置的异常处理类
<code><?php <br />// 自定义一个异常处理类<br>class MyException extends Exception{ // 重定义构造器使 message 变为必须被指定的属性<br> public function __construct($message, $code = 0) {<br> // 自定义的代码 // 确保所有变量都被正确赋值<br> parent::__construct($message, $code);<br>}<br>// 自定义字符串输出的样式<br>public function __toString() {<br> return __CLASS__ . ": [{$this->code}]: {$this->message}\n";<br>}<br>public function customFunction() {<br> echo "A Custom function for this type of exception\n";<br> }<br>}<br><span>//</span>创建一个用于测试异常处理机制的类<br>class TestException{<br>public $var;<br>const THROW_NONE = 0;<br>const THROW_CUSTOM = 1;<br>const THROW_DEFAULT = 2;<br>function __construct($avalue = self::THROW_NONE) {<br>switch ($avalue) {<br>case self::THROW_CUSTOM:<br>// 抛出自定义异常<br>throw new MyException('1 is an invalid parameter', 5);<br>break;<br>case self::THROW_DEFAULT:<br>// 抛出默认的异常<br>throw new Exception('2 isnt allowed as a parameter', 6);<br>break;<br>default:<br>// 没有异常的情况下,创建一个对象<br>$this->var = $avalue;<br>break;<br>}<br>}<br>}<br>// 例子 1<br>try {<br>$o = new TestException(TestException::THROW_CUSTOM);<br>} catch (MyException $e) { // 捕获异常<br>echo "Caught my exception\n", $e;<br>$e->customFunction();<br>} catch (Exception $e) { // 被忽略<br>echo "Caught Default Exception\n", $e;<br>}<br>// 执行后续代码<br>var_dump($o);<br>echo "\n\n";<br>// 例子 2<br>try {<br>$o = new TestException(TestException::THROW_DEFAULT);<br>} catch (MyException $e) { // 不能匹配异常的种类,被忽略<br>echo "Caught my exception\n", $e;<br>$e->customFunction();<br>} catch (Exception $e) { // 捕获异常<br>echo "Caught Default Exception\n", $e;<br>}<br>// 执行后续代码<br>var_dump($o);<br>echo "\n\n";<br>// 例子 3<br>try {<br>$o = new TestException(TestException::THROW_CUSTOM);<br>} catch (Exception $e) { // 捕获异常<br>echo "Default Exception caught\n", $e;<br>}<br>// 执行后续代码<br>var_dump($o);<br>echo "\n\n";<br>// 例子 4<br>try {<br>$o = new TestException();<br>} catch (Exception $e) { // 没有异常,被忽略<br>echo "Default Exception caught\n", $e;<br>}<br>// 执行后续代码<br>var_dump($o);<br>echo "\n\n";<br>?> 12.生成器 <code><code>生成器允许你在 foreach代码块中写代码来迭代一组数据而不需要在内存中创建一个数组, 那会使你的内存达到上限,或者会占据可观的处理时间。相反,你可以写一个生成器函数,就像一个普通的自定义函数一样, 和普通函数只返回一次不同的是, 生成器可以根据需要 yield 多次,以便生成需要迭代的值。
<code><?php <br />function xrange($start, $limit, $step = 1) {<br> if ($start if ($step throw new LogicException('Step must be +ve');<br>}<br> for ($i = $start; $i yield $i;<br> }<br> } else {<br> if ($step >= 0) {<br> throw new LogicException('Step must be -ve');<br> }<br> for ($i = $start; $i >= $limit; $i += $step) {<br> yield $i;<br> }<br> }<br>}<br>/* Note that both range() and xrange() result in the same<br>* output below. */<br>echo 'Single digit odd numbers from range(): ';<br>foreach (range(1, 9, 2) as $number) {<br> echo "$number ";<br>}<br>echo "\n";<br>echo 'Single digit odd numbers from xrange(): ';<br>foreach (xrange(1, 9, 2) as $number) {<br> echo "$number ";<br>}<br>?>Single digit odd numbers from range(): 1 3 5 7 9 Single digit odd numbers from xrange(): 1 3 5 7 9
The primary advantage of generators is their simplicity. Much less boilerplate code has to be written compared to implementing anIterator class, and the code is generally much more readable. For example, the following function and class are equivalent:
<code><?php <br />function getLinesFromFile($fileName) {<br> if (!$fileHandle = fopen($fileName, 'r')) {<br> return;<br>}<br>while (false !== $line = fgets($fileHandle)) {<br> yield $line;<br>}<br>fclose($fileHandle);<br>}<br>// versus...<br>class LineIterator implements Iterator {<br> protected $fileHandle;<br> protected $line;<br> protected $i;<br> public function __construct($fileName) {<br> if (!$this->fileHandle = fopen($fileName, 'r')) {<br> throw new RuntimeException('Couldn\'t open file "' . $fileName . '"');<br> }<br> }<br> public function rewind() {<br> fseek($this->fileHandle, 0);<br> $this->line = fgets($this->fileHandle);<br> $this->i = 0;<br> }<br> public function valid() {<br> return false !== $this->line;<br> }<br> public function current() {<br> return $this->line;<br> }<br> public function key() {<br> return $this->i;<br> }<br> public function next() {<br> if (false !== $this->line) {<br> $this->line = fgets($this->fileHandle);<br> $this->i++;<br> }<br> }<br> public function __destruct() {<br> fclose($this->fileHandle);<br> }<br> }<br>?> 13.引用 <code><code> <code><?php <br />$a =& $b; //这意味着 <var><var>$a</var></var> 和 <var><var>$b</var></var> 指向了同一个变量。<var><var>$a</var></var> 和 <var><var>$b</var></var> 在这里是完全相同的,这并不是 <var><var>$a</var></var> 指向了 <var><var>$b</var></var> 或者· //相反,而是 <var><var>$a</var></var> 和 <var><var>$b</var></var> 指向了同一个地方。<br>?> <code>如果具有引用的数组被拷贝,其值不会解除引用。对于数组传值给函数也是如此。如果对一个未定义的变量进行引用赋值、引用参数传递或引用返回,则会自动创建该变量。
function foo(&$var) { }
foo($a); // $a is "created" and assigned to null
$b = array();
foo($b['b']);
var_dump(array_key_exists('b', $b)); // bool(true)
$c = new StdClass;
foo($c->d);
var_dump(property_exists($c, 'd')); // bool(true)
?>
同样的语法可以用在函数中,它返回引用,以及用在 new运算符中(PHP 4.0.4 以及以后版本):
<code><span><?php <br />$bar =& new fooclass();<br>$foo =& find_var($bar);<br>?></span>如果在一个函数内部给一个声明为 global的变量赋于一个引用,该引用只在函数内部可见。可以通过使用 $GLOBALS 数组避免这一点。在函数内引用全局变量:
<code><span><?php <br />$var1 = "Example variable";<br>$var2 = "";<br>function global_references($use_globals){<br> global $var1, $var2;<br> if (!$use_globals) {<br> $var2 =& $var1; // visible only inside the function<br> } else {<br> $GLOBALS["var2"] =& $var1; // visible also in global context<br> }<br>}<br>global_references(false);<br>echo "var2 is set to '$var2'\n"; // var2 is set to ''<br>global_references(true);<br>echo "var2 is set to '$var2'\n"; // var2 is set to 'Example variable'<br>?></span> 把 global $var; 当成是 $var =& $GLOBALS['var']; 的简写。从而将其它引用赋给 $var 只改变了本地变量的引用。如果在 foreach语句中给一个具有引用的变量赋值,被引用的对象也被改变。
$ref = 0;
$row =& $ref;
foreach (array(1, 2, 3) as $row) {// do something}
echo $ref; // 3 - last element of the iterated array
?>
引用做的第二件事是用引用传递变量。这是通过在函数内建立一个本地变量并且该变量在呼叫范围内引用了同一个内容来实现的。例如:
<code><span><?php <br />function foo(&$var){<br> $var++;<br>}<br>$a=5;<br>foo($a);<br>?></span> 将使 $a 变成 6。这是因为在 foo 函数中变量 $var 指向了和 $a 指向的同一个内容。更多详细解释见引用传递。 引用做的第三件事是引用返回。引用不是指针。可以将一个变量通过引用传递给函数,这样该函数就可以修改其参数的值。
<code><span><?php <br />function foo(&$var){<br>$var++;<br>}<br>$a=5;<br>foo($a);// $a is 6 here<br>?></span> 注意在函数调用时没有引用符号——只有函数定义中有。光是函数定义就足够使参数通过引用来正确传递了以下内容可以通过引用传递:
变量,例如 foo($a);New 语句,例如 foo(new foobar());从函数中返回的引用
任何其它表达式都不能通过引用传递,结果未定义。
<code><span><?php <br />function bar(){ // Note the missing &<br>$a = 5;<br>return $a;<br>}<br>foo(bar()); // 自 PHP 5.0.5 起导致致命错误<br>foo($a = 5) // 表达式,不是变量<br>foo(5) // 导致致命错误<br>?></span>引用返回用在当想用函数找到引用应该被绑定在哪一个变量上面时。不要用返回引用来增加性能,引擎足够聪明来自己进行优化。仅在有合理的技术原因时才返回引用!要返回引用,使用此语法:
<code><span><?php <br />class foo {<br> public $value = 42;<br> public function &getValue() {<br> return $this->value;<br> }<br>}<br>$obj = new foo;<br>$myValue = &$obj->getValue(); // $myValue is a reference to $obj->value, which is 42.<br>$obj->value = 2;<br>echo $myValue; // prints the new value of $obj->value, i.e. 2.<br>?></span> 本例中 getValue 函数所返回的对象的属性将被赋值,而不是拷贝,就和没有用引用语法一样。和参数传递不同,这里必须在两个地方都用 &符号——指出返回的是一个引用,而不是通常的一个拷贝,同样也指出 $myValue是作为引用的绑定,而不是通常的赋值。当 unset 一个引用,只是断开了变量名和变量内容之间的绑定。这并不意味着变量内容被销毁了。 <code><span><?php <br />$a = 1;<br>$b =& $a;<br>unset($a);<br>?></span> 不会 unset $b,只是 $a。引用定位: global引用:当用 global $var 声明一个变量时实际上建立了一个到全局变量的引用。也就是说和这样做是相同的: <code><span><?php <br />$var =& $GLOBALS["var"]; //这意味着,例如,unset <var><var>$var</var></var> 不会 unset 全局变量。<br>?></span> $this:在一个对象的方法中,$this 永远是调用它的对象的引用。14.预定义变量
超全局变量 — 超全局变量是在全部作用域中始终可用的内置变量PHP 中的许多预定义变量都是"超全局的",这意味着它们在一个脚本的全部作用域中都可用。在函数或方法中无需执行 global $variable; 就可以访问它们。这些超全局变量是:
$GLOBALS;$_SERVER;$_GET;$_POST;$_FILES;$_COOKIE;$_SESSION;$_REQUEST;$_ENV默认情况下,所有的超全局变量都是可用的。但是,有一些指令会影响这种可用性。
$GLOBALS — 引用全局作用域中可用的全部变量一个包含了全部变量的全局组合数组。变量的名字就是数组的键。
<code><span><?php <br />function test() {<br>$foo = "local variable";<br>echo '$foo in global scope: ' . $GLOBALS["foo"] . "\n";//$foo in global scope: Example content<br>echo '$foo in current scope: ' . $foo . "\n";//$foo in current scope: local variable<br>}<br>$foo = "Example content";<br>test();<br>?></span>"Superglobal"也称为自动化的全局变量。这就表示其在脚本的所有作用域中都是可用的。不需要在函数或方法中用global $variable; 来访问它。与所有其他超全局变量不同,$GLOBALS在PHP中总是可用的。
$_SERVER 是一个包含了诸如头信息(header)、路径(path)、以及脚本位置(script locations)等等信息的数组。这个数组中的项目由
Web 服务器创建。在 $_SERVER 中,你也许能够,也许不能够找到下面的这些元素。列举:
'PHP_SELF':当前执行脚本的文件名,与 document root 有关。例如,在地址为 http://example.com/test.php/foo.bar 的脚本中使用
$_SERVER['PHP_SELF'] 将得到 /test.php/foo.bar。
'SERVER_ADDR':当前运行脚本所在的服务器的 IP 地址。
'SERVER_NAME':当前运行脚本所在的服务器的主机名。如果脚本运行虚拟主机,该名称是由那个虚拟主机所设置的值决定。
'SERVER_PROTOCOL':请求页面时通信协议的名称和版本。例如,"HTTP/1.0"。
'REQUEST_METHOD':访问页面使用的请求方法;例如,"GET", "HEAD","POST","PUT"。
'REQUEST_TIME':请求开始时的时间戳。从 PHP 5.1.0 起可用。
'QUERY_STRING':query string(查询字符串),如果有的话,通过它进行页面访问。
'HTTP_HOST':当前请求头中 Host: 项的内容,如果存在的话。
'HTTP_REFERER':引导用户代理到当前页的前一页的地址(如果存在)。由 user agent 设置决定。并不是所有的用户代理都会设置该项,有的还提供了修改 HTTP_REFERER 的功能。简言之,该值并不可信。
'HTTP_USER_AGENT':当前请求头中 User-Agent: 项的内容,如果存在的话。该字符串表明了访问该页面的用户代理的信息。
'REMOTE_ADDR':浏览当前页面的用户的 IP 地址。
'REMOTE_HOST':浏览当前页面的用户的主机名。DNS 反向解析不依赖于用户的 REMOTE_ADDR。
'SERVER_PORT':Web 服务器使用的端口。默认值为 "80"。如果使用 SSL 安全连接,则这个值为用户设置的 HTTP 端口。
$_GET:通过 URL 参数传递给当前脚本的变量的数组。GET 是通过 urldecode() 传递的。
$_POST:通过 HTTP POST 方法传递给当前脚本的变量的数组。
$_FILES:通过 HTTP POST 方式上传到当前脚本的项目的数组。
$_REQUEST — HTTP Request 变量,以命令行方式运行时,将不包含 argv 和 argc 信息;它们将存在于 $_SERVER数组。
由于 $_REQUEST 中的变量通过 GET,POST 和 COOKIE 输入机制传递给脚本文件,因此可以被远程用户篡改而并不可信。这个数组的项目及其顺序依赖于 PHP 的 variables_order 指令的配置。
$_SESSION:当前脚本可用 SESSION 变量的数组。
move_uploaded_file() - 将上传的文件移动到新位置;import_request_variables() - 将 GET/POST/Cookie 变量导入到全局作用域中;session_start() - 启动新会话或者重用现有会话;getenv() - 获取一个环境变量的值;$_ENV:通过环境方式传递给当前脚本的变量的数组。这些变量被从 PHP 解析器的运行环境导入到 PHP 的全局命名空间。很多是由支持 PHP 运行的 Shell 提供的,并且不同的系统很可能运行着不同种类的 Shell,所以不可能有一份确定的列表。请查看你的 Shell 文档来获取定义的环境变量列表。其他环境变量包含了 CGI 变量,而不管 PHP 是以服务器模块还是 CGI 处理器的方式运行。
$_COOKIE:通过 HTTP Cookies 方式传递给当前脚本的变量的数组。setcookie() - Send a cookie
$php_errormsg — 前一个错误信息;$php_errormsg 变量包含由 PHP 生成的最新错误信息。这个变量只在错误发生的作用域内可用,并且要求 track_errors 配置项是开启的(默认是关闭的)。如果用户定义了错误处理句柄(set_error_handler())并且返回 <code>FALSE 的时候,$php_errormsg 就会被设置。
<code><span><?php <br />@strpos();<br>echo $php_errormsg; //Wrong parameter count for strpos()<br>?></span>$HTTP_RAW_POST_DATA — 原生POST数据。$HTTP_RAW_POST_DATA 包含 POST 提交的原始数据。参见 always_populate_raw_post_data一般而言,使用 php://input代替 $HTTP_RAW_POST_DATA。
$http_response_header — HTTP 响应头:$http_response_header数组与 get_headers() 函数类似。当使用HTTP 包装器时,$http_response_header 将会被 HTTP 响应头信息填充。$http_response_header 将被创建于局部作用域中。
<code><span><?php <br />function get_contents() {<br> file_get_contents("http://example.com");<br> var_dump($http_response_header);<br>}<br>get_contents();<br>var_dump($http_response_header);<br>?></span>$argc — 传递给脚本的参数数目:包含当运行于命令行下时传递给当前脚本的参数的数目。脚本的文件名总是作为参数传递给当前脚本,因此 $argc 的最小值为 1。这个变量仅在 register_argc_argv 打开时可用。
$argv — 传递给脚本的参数数组:包含当运行于命令行下时传递给当前脚本的参数的数组。第一个参数总是当前脚本的文件名,因此 $argv[0] 就是脚本文件名。这个变量仅在 register_argc_argv 打开时可用。
Exception是所有异常的基类。类摘要:
Exception { /* 属性 */ protectedstring$message ; protectedint$code ; protectedstring$file ; protectedint$line ; /* 方法 */ public__construct ([ string<code>$message = "" [, int<code>$code = 0 [, Exception<code>$previous = <code>NULL ]]] ) finalpublicstringgetMessage ( void ) finalpublicExceptiongetPrevious ( void ) finalpublicintgetCode ( void ) finalpublicstringgetFile ( void ) finalpublicintgetLine ( void ) finalpublicarraygetTrace ( void ) finalpublicstringgetTraceAsString ( void ) publicstring__toString ( void ) finalprivatevoid__clone ( void ) } 属性:message:异常消息内容;code:异常代码;file:抛出异常的文件名;line:抛出异常在该文件中的行号Exception::__construct — 异常构造函数
参数:message:抛出的异常消息内容。code:异常代码。previous:异常链中的前一个异常。Exception::getMessage — 获取异常消息内容
参数:此函数没有参数。Exception::getPrevious — 返回异常链中的前一个异常
参数:Exception::getPrevious — 返回异常链中的前一个异常。追踪异常,并循环打印。 <code><span><?php <br />class MyCustomException extends Exception {}<br>function doStuff() {<br> try {<br> throw new InvalidArgumentException("You are doing it wrong!", 112);<br> } catch(Exception $e) {<br> throw new MyCustomException("Something happend", 911, $e);<br> }<br>}<br>try {<br> doStuff();<br> } catch(Exception $e) {<br> do {<br> printf("%s:%d %s (%d) [%s]\n", $e->getFile(), $e->getLine(), $e->getMessage(), $e- >getCode(), get_class($e));<br> } while($e = $e->getPrevious());<br> }<br>?></span>以上例程的输出类似于:
<span>/home/bjori/ex.php:8 Something happend (911) [MyCustomException] /home/bjori/ex.php:6 You are doing it wrong! (112) [InvalidArgumentException] </span>
Exception::getCode — 获取异常代码
参数:此函数没有参数。Exception::getFile — 获取发生异常的程序文件名称
参数:此函数没有参数。Exception::getLine — 获取发生异常的代码在文件中的行号
参数:此函数没有参数。Exception::getTrace — 获取异常追踪信息
参数:此函数没有参数。Exception::getTraceAsString — 获取字符串类型的异常追踪信息
参数:此函数没有参数。Exception::__toString — 将异常对象转换为字符串
参数:此函数没有参数。Exception::__clone — 异常克隆
参数:此函数没有参数。没有返回值,异常被不允许克隆。ErrorException::__construct — 异常构造函数
参数:message:抛出的异常消息内容。code:异常代码。severity:异常的严重级别。filename:抛出异常所在的文件名。lineno:抛出异常所在的行号。previous:异常链中的前一个异常。ErrorException::getSeverity — 获取异常的严重程度
参数:此函数没有参数。 <code><span><?php <br />try {<br> throw new ErrorException("Exception message", 0, 75);<br>} catch(ErrorException $e) {<br> echo "This exception severity is: " . $e->getSeverity();<br>}<br>?></span> 16.预定义接口 Traversable(遍历)接口:检测一个类是否可以使用 foreach 进行遍历的接口。无法被单独实现的基本抽象接口。相反它必须由 IteratorAggregate 或 Iterator 接口实现。实现此接口的内建类可以使用 foreach 进行遍历而无需实现 IteratorAggregate 或 Iterator 接口。这是一个无法在 PHP 脚本中实现的内部引擎接口。IteratorAggregate 或 Iterator 接口可以用来代替它。
Traversable { } 这个接口没有任何方法,它的作用仅仅是作为所有可遍历类的基本接口。 Iterator(迭代器)接口:可在内部迭代自己的外部迭代器或类的接口。
IteratorextendsTraversable { /* 方法 */ abstractpublicmixedcurrent ( void ) abstractpublicscalarkey ( void ) abstractpublicvoidnext ( void ) abstractpublicvoidrewind ( void ) abstractpublicbooleanvalid ( void ) }Iterator::current — 返回当前元素:没有参数,可返回任何类型。
Iterator::key — 返回当前元素的键:没有参数,成功返回标量,失败则返回null。
Iterator::next — 向前移动到下一个元素:没有参数,任何返回都将被忽略。此方法在 foreach 循环之后被调用。
Iterator::rewind — 返回到迭代器的第一个元素:当开始一个 foreach 循环时,这是第一个被调用的方法。它将不会在 foreach 循环之后被调用。没有参数,任何返回都将被忽略。
Iterator::valid — 检查当前位置是否有效:此方法在 Iterator::rewind() 和 Iterator::next() 方法之后被调用以此用来检查当前位置是否有效。没有参数,返回将被转换为布尔型。成功时返回 <code>TRUE, 或者在失败时返回 <code>FALSE。
IteratorAggregate::getIterator — 获取一个外部迭代器:没有参数,实现了 Iterator 或 Traversable 接口的类的一个实例。
ArrayAccess(数组式访问)接口:提供像访问数组一样访问对象的能力的接口。
ArrayAccess { /* 方法 */ abstractpublicbooleanoffsetExists ( mixed<code>$offset ) abstractpublicmixedoffsetGet ( mixed<code>$offset ) abstractpublicvoidoffsetSet ( mixed<code>$offset , mixed<code>$value ) abstractpublicvoidoffsetUnset ( mixed<code>$offset ) }ArrayAccess::offsetExists — 检查一个偏移位置是否存在:对一个实现了 ArrayAccess 接口的对象使用 isset() 或 empty() 时,此方法将执行。当使用 empty() 并且仅当 ArrayAccess::offsetExists() 返回 <code>TRUE 时,ArrayAccess::offsetGet() 将被调用以检查是为否空。参数:offset 需要检查的偏移位置。成功时返回 <code>TRUE, 或者在失败时返回 <code>FALSE。如果一个非布尔型返回值被返回,将被转换为布尔型。
<code><span><?php <br />class obj implements arrayaccess {<br> public function offsetSet($offset, $value) {<br> var_dump(__METHOD__);<br>}<br>public function offsetExists($var) {<br> var_dump(__METHOD__);<br> if ($var == "foobar") {<br> return true;<br> }<br> return false;<br>}<br>public function offsetUnset($var) {<br> var_dump(__METHOD__);<br> }<br>public function offsetGet($var) {<br> var_dump(__METHOD__);<br> return "value";<br> }<br>}<br>$obj = new obj;<br>echo "Runs obj::offsetExists()\n";<br>var_dump(isset($obj["foobar"]));<br>echo "\nRuns obj::offsetExists() and obj::offsetGet()\n";<br>var_dump(empty($obj["foobar"]));<br>echo "\nRuns obj::offsetExists(), *not* obj:offsetGet() as there is nothing to get\n";<br>var_dump(empty($obj["foobaz"]));<br>?></span>以上例程的输出类似于:
<span>Runs obj::offsetExists() string(17) "obj::offsetExists" bool(true) Runs obj::offsetExists() and obj::offsetGet() string(17) "obj::offsetExists" string(14) "obj::offsetGet" bool(false) Runs obj::offsetExists(), *not* obj:offsetGet() as there is nothing to get string(17) "obj::offsetExists" bool(true) </span>
ArrayAccess::offsetGet — 获取一个偏移位置的值:当检查一个偏移位置是否为 empty() 时,此方法被执行。
参数:offset 需要获取的偏移位置。返回值:可返回任何类型。ArrayAccess::offsetSet — 设置一个偏移位置的值:参数:offset 待设置的偏移位置。value 需要设置的值。没有返回值。
如果另一个值不可用,那么 <code>offset 参数将被设置为 <code>NULL。
ArrayAccess::offsetUnset — 复位一个偏移位置的值:当使用 (unset) 进行类型转换时,该方法不会被调用。
<code>参数:offset 待复位的偏移位置。没有返回值。
序列化接口:
Serializable::serialize — 对象的字符串表示。这个方法担当着对象析构器的角色。在此方法之后,__destruct() 方法将不会被调用。此函数没有参数,返回值:返回对象的字符串表示或者 <code>NULL 。
Serializable::unserialize — 构造对象。这个方法担当着对象构造器的角色。在此方法之后,__construct() 将不会被调用。参数:serialized 对象的字符串表示。
Closure::__construct — 用于禁止实例化的构造函数。这个方法仅用于禁止实例化一个 Closure 类的对象。这个类的对象的创建方法写在 匿名函数 页。此函数没有参数,没有返回值。
Closure::bind — 复制一个闭包,绑定指定的$this对象和类作用域。这个方法是 Closure::bindTo() 的静态版本。
参数:closure 需要绑定的匿名函数。newthis 需要绑定到匿名函数的对象,或者 <code>NULL 创建未绑定的闭包。newscope 想要绑定给闭包的类作用域,或者 'static' 表示不改变。如果传入一个对象,则使用这个对象的类型名。 类作用域用来决定在闭包中 $this 对象的 私有、保护方法 的可见性。返回一个新的 Closure 对象 或者在失败时返回 <code>FALSE
<code><span><?php <br />class A {<br> private static $sfoo = 1;<br> private $ifoo = 2;<br>}<br>$cl1 = static function() {<br> return A::$sfoo;<br>};<br>$cl2 = function() {<br> return $this->ifoo;<br>};<br>$bcl1 = Closure::bind($cl1, null, 'A');<br>$bcl2 = Closure::bind($cl2, new A(), 'A');<br>echo $bcl1(), "\n"; //1<br>echo $bcl2(), "\n"; //2<br>?></span>
Closure::bindTo — 复制当前闭包对象,绑定指定的$this对象和类作用域。创建并返回一个 匿名函数, 它与当前对象的函数体相同、绑定了同样变量,但可以绑定不同的对象,也可以绑定新的类作用域。"绑定的对象"决定了函数体中的 $this的取值,"类作用域"代表一个类型、决定在这个匿名函数中能够调用哪些 私有 和 保护 的方法。 也就是说,此时 $this 可以调用的方法,与 <code>newscope 类的成员函数是相同的。静态闭包不能有绑定的对象( <code>newthis 参数的值应该设为 <code>NULL)不过仍然可以用 bubdTo 方法来改变它们的类作用域。如果你只是想要复制一个匿名函数,可以用 cloning 代替。
参数:newthis 绑定给匿名函数的一个对象,或者 <code>NULL 来取消绑定。newscope 关联到匿名函数的类作用域,或者 'static' 保持当前状态。如果是一个对象,则使用这个对象的类型为心得类作用域。 这会决定绑定的对象的 保护、私有成员 方法的可见性。返回值:返回新创建的 Closure 对象 或者在失败时返回 <code>FALSE
<code><span><?php <br />class A {<br> function __construct($val) {<br> $this->val = $val;<br> }<br> function getClosure() {<br> //returns closure bound to this object and scope<br> return function() { return $this->val; };<br> }<br>}<br>$ob1 = new A(1);<br>$ob2 = new A(2);<br>$cl = $ob1->getClosure();<br>echo $cl(), "\n"; //1<br>$cl = $cl->bindTo($ob2);<br>echo $cl(), "\n"; //2<br>?></span> 17.上下文选项和参数
套接字上下文选项可用于所有工作在套接字上的封装协议,像 tcp, http 和 ftp.
<code><span><?php <br />// connect to the internet using the '192.168.0.100' IP<br>$opts = array(<br> 'socket' => array(<br> 'bindto' => '192.168.0.100:0',<br> ),<br>);<br>// connect to the internet using the '192.168.0.100' IP and port '7000'<br>$opts = array(<br> 'socket' => array(<br> 'bindto' => '192.168.0.100:7000',<br> ),<br>);<br>// connect to the internet using port '7000'<br>$opts = array(<br> 'socket' => array(<br> 'bindto' => '0:7000',<br> ),<br>);<br>// create the context...<br>$context = stream_context_create($opts);<br>// ...and use it to fetch the data<br>echo file_get_contents('http://www.example.com', false, $context);<br>?></span>HTTP context 选项 — HTTP context 的选项列表。提供给 http:// 和 https:// 传输协议的 context 选项。 transports.可选项:
FTP context options — FTP context option listing
SSL 上下文选项 — SSL 上下文选项清单。ssl:// 和 tls://传输协议上下文选项清单。可选项:好多。
CURL context options — CURL 上下文选项列表。CURL 上下文选项在 CURL 扩展被编译(通过 --with-curlwrappers configure选项)时可用。可选项:
<code><span><?php <br />$postdata = http_build_query(<br> array(<br> 'var1' => 'some content',<br> 'var2' => 'doh'<br> )<br>);<br>$opts = array('http' =><br> array(<br> 'method' => 'POST',<br> 'header' => 'Content-type: application/x-www-form-urlencoded',<br> 'content' => $postdata<br> )<br>);<br>$context = stream_context_create($opts);<br>$result = file_get_contents('http://example.com/submit.php', false, $context);<br>?></span>
Phar 上下文(context)选项 — Phar 上下文(context)选项列表。phar:// 封装(wrapper)的上下文(context)选项。可选项:<code>compressint Phar compression constants 中的一个。<code>metadatamixed Phar 元数据(metadata)。查看 Phar::setMetadata()。
Context 参数 — Context 参数列表。这些参数(parameters)可以设置为由函数 stream_context_set_params() 返回的 context。参数:<code>notificationcallable 当一个流(stream)上发生事件时,callable 将被调用。
18.支持的协议和封装协议
file:// — 访问本地文件系统。文件系统 是 PHP 使用的默认封装协议,展现了本地文件系统。 当指定了一个相对路径(不以/、\、\\或 Windows 盘符开头的路径)提供的路径将基于当前的工作目录。 在很多情况下是脚本所在的目录,除非被修改了。 使用 CLI 的时候,目录默认是脚本被调用时所在的目录。
在某些函数里,例如 fopen() 和 file_get_contents(), include_path 会可选地搜索,也作为相对的路径。
属性 | 支持 |
---|---|
受 allow_url_fopen 影响 | No |
允许读取 | Yes |
允许写入 | Yes |
允许添加 | Yes |
允许同时读和写 | Yes |
支持 stat() | Yes |
支持 unlink() | Yes |
支持 rename() | Yes |
支持 mkdir() | Yes |
支持 rmdir() | Yes |
http:// -- https:// — 访问 HTTP(s) 网址。允许通过 HTTP 1.0 的 GET方法,以只读访问文件或资源。 HTTP 请求会附带一个 Host: 头,用于兼容基于域名的虚拟主机。 如果在你的 php.ini 文件中或字节流上下文(context)配置了 user_agent 字符串,它也会被包含在请求之中。数据流允许读取资源的 body,而 headers 则储存在了 $http_response_header 变量里。
如果需要知道文档资源来自哪个 URL(经过所有重定向的处理后), 需要处理数据流返回的系列响应报头(response headers)。
属性 | 支持 |
---|---|
受 allow_url_fopen 限制 | Yes |
允许读取 | Yes |
允许写入 | No |
允许添加 | No |
允许同时读和写 | N/A |
支持 stat() | No |
支持 unlink() | No |
支持 rename() | No |
支持 mkdir() | No |
支持 rmdir() | No |
ftp:// -- ftps:// — 访问 FTP(s) URLs。允许通过 FTP 读取存在的文件,以及创建新文件。 如果服务器不支持被动(passive)模式的 FTP,连接会失败。
打开文件后你既可以读也可以写,但是不能同时进行。 当远程文件已经存在于 ftp 服务器上,如果尝试打开并写入文件的时候, 未指定上下文(context)选项 overwrite,连接会失败。 如果要通过 FTP 覆盖存在的文件, 指定上下文(context)的 overwrite 选项来打开、写入。 另外可使用 FTP 扩展来代替。如果你设置了 php.ini 中的 from 指令, 这个值会作为匿名(anonymous)ftp 的密码。
属性 | PHP 4 | PHP 5 |
---|---|---|
受 allow_url_fopen 影响 | Yes | Yes |
允许读取 | Yes | Yes |
允许写入 | Yes (仅支持新文件) | Yes (新文件/启用 <code>overwrite 后已存在的文件) |
允许添加 | No | Yes |
允许同时读和写 | No | No |
支持 stat() | No | 自 5.0.0 起:仅仅 filesize()、 filetype()、 file_exists()、 is_file() 和 is_dir()。 自 PHP 5.1.0 起: filemtime()。 |
支持 unlink() | No | Yes |
支持 rename() | No | Yes |
支持 mkdir() | No | Yes |
支持 rmdir() | No | Yes |
php:// — 访问各个输入/输出流(I/O streams)。PHP 提供了一些杂项输入/输出(IO)流,允许访问 PHP 的输入输出流、标准输入输出和错误描述符, 内存中、磁盘备份的临时文件流以及可以操作其他读取写入文件资源的过滤器。
php://stdin、php://stdout 和 php://stderr 允许直接访问 PHP 进程相应的输入或者输出流。 数据流引用了复制的文件描述符,所以如果你打开 php://stdin 并在之后关了它, 仅是关闭了复制品,真正被引用的 <code>STDIN 并不受影响。 注意 PHP 在这方面的行为有很多 BUG 直到 PHP 5.2.1。 推荐你简单使用常量 <code>STDIN、 <code>STDOUT 和 <code>STDERR 来代替手工打开这些封装器。
php://stdin 是只读的, php://stdout 和 php://stderr 是只写的。
php://input 是个可以访问请求的原始数据的只读流。 POST 请求的情况下,最好使用 php://input 来代替 $HTTP_RAW_POST_DATA,因为它不依赖于特定的 php.ini 指令。 而且,这样的情况下 $HTTP_RAW_POST_DATA 默认没有填充, 比激活 always_populate_raw_post_data潜在需要更少的内存。 enctype="multipart/form-data" 的时候 php://input 是无效的。
php://output 是一个只写的数据流, 允许你以 print 和 echo 一样的方式 写入到输出缓冲区。
php://fd 允许直接访问指定的文件描述符。 例如 php://fd/3 引用了文件描述符 3。
php://memory 和 php://temp 是一个类似文件 包装器的数据流,允许读写临时数据。 两者的唯一区别是 php://memory 总是把数据储存在内存中, 而 php://temp 会在内存量达到预定义的限制后(默认是 2MB)存入临时文件中。 临时文件位置的决定和 sys_get_temp_dir() 的方式一致。php://temp 的内存限制可通过添加 /maxmemory:NN来控制,NN 是以字节为单位、保留在内存的最大数据量,超过则使用临时文件。
php://filter 是一种元封装器, 设计用于数据流打开时的筛选过滤应用。 这对于一体式(all-in-one)的文件函数非常有用,类似 readfile()、 file() 和 file_get_contents(), 在数据流内容读取之前没有机会应用其他过滤器。php://filter 目标使用以下的参数作为它路径的一部分。 复合过滤链能够在一个路径上指定。
属性 | 支持 |
---|---|
首先于 allow_url_fopen | No |
首先于 allow_url_include | 仅 php://input、 php://stdin、 php://memory 和 php://temp。 |
允许读取 | 仅 php://stdin、 php://input、 php://fd、 php://memory 和 php://temp。 |
允许写入 | 仅 php://stdout、 php://stderr、 php://output、 php://fd、 php://memory 和php://temp。 |
允许追加 | 仅 php://stdout、 php://stderr、 php://output、 php://fd、 php://memory 和php://temp(等于写入) |
允许同时读写 | 仅 php://fd、 php://memory 和 php://temp。 |
支持 stat() | 仅 php://memory 和 php://temp。 |
支持 unlink() | No |
支持 rename() | No |
支持 mkdir() | No |
支持 rmdir() | No |
仅仅支持 stream_select() | php://stdin、 php://stdout、 php://stderr、 php://fd 和 php://temp。 |
zlib:// -- bzip2:// -- zip:// — 压缩流。zlib: PHP 4.0.4 - PHP 4.2.3(仅支持带 fopencookie 的系统)
compress.zlib:// 和 compress.bzip2:// PHP 4.3.0 及以上
zlib: 的功能类似 gzopen(),但是 其数据流还能被 fread() 和其他文件系统函数使用。 自 PHP 4.3.0 后这个不建议被使用,因为会和其他带":"字符的文件名混淆; 请使用 compress.zlib:// 作为替代。
compress.zlib://、 compress.bzip2://和 gzopen()、bzopen()是相等的。并且可以在不支持 fopencookie 的系统中使用。
ZIP 扩展 注册了 zip: 封装协议。可选项
data:// — 数据(RFC 2397)。用法:data://text/plain;base64,
属性 | 支持 |
---|---|
受限于 allow_url_fopen | No |
受限于 allow_url_include | Yes |
允许读取 | Yes |
允许写入 | No |
允许追加 | No |
允许同时读写 | No |
支持 stat() | No |
支持 unlink() | No |
支持 rename() | No |
支持 mkdir() | No |
支持 rmdir() | No |
打印 data:// 的内容:
<code><span><?php <br />// 打印 "I love PHP"<br>echo file_get_contents('data://text/plain;base64,SSBsb3ZlIFBIUAo=');<br>?></span>获取媒体类型:
<code><span><?php <br />$fp = fopen('data://text/plain;base64,', 'r');<br>$meta = stream_get_meta_data($fp);<br>echo $meta['mediatype']; // 打印 "text/plain"<br>?></span>glob:// — 查找匹配的文件路径模式。用法:glob://
属性 | 支持 |
---|---|
受限于 allow_url_fopen | No |
受限于 allow_url_include | No |
允许读取 | No |
允许写入 | No |
允许附加 | No |
允许同时读写 | No |
支持 stat() | No |
支持 unlink() | No |