manual-php
Version:
1 lines • 439 kB
JSON
{"./":{"url":"./","title":"PHP","keywords":"","body":"PHP PHP 全称 PHP: Hypertext Preprocessor ,超文本预处理器。 它是一种被广泛应用的开源脚本语言,可以嵌入到 HTML 文档中去执行,主要适用于 Web 开发领域。 "},"docs/语言参考.html":{"url":"docs/语言参考.html","title":"语言参考","keywords":"","body":"语言参考 基本语法 PHP 标记 从 HTML 中分离 指令分隔符 注释 类型 Boolean 布尔类型 Integer 整型 Float 浮点型 String 字符串 Array 数组 Object 对象 Resource 资源类型 NULL Callable 可调用类型 类型转换的判别 变量 基本语法 变量范围 可变变量 来自 PHP 之外的变量 常量 基本语法 魔术常量 表达式 运算符 运算符优先级 算数运算符 赋值运算符 位运算符 比较运算符 错误控制运算符 执行运算符 递增递减运算符 逻辑运算符 字符串运算符 数组运算符 类型运算符 函数 用户自定义函数 函数的参数 返回值 可变函数 匿名函数 类与对象 基本语法 属性 类常量 类的自动加载 构造函数和析构函数 访问控制 对象继承 范围解析操作符 Static 关键字 抽象类 对象接口 Trait 匿名类 重载 遍历对象 魔术方法 Final 关键字 对象复制 对象比较 类型约束 后期静态绑定 对象和引用 对象序列化 命名空间 基本语法 定义子命名空间 在同一个文件中定义多个命名空间 使用命名空间 - 基础 命名空间和动态语言特征 namespace 关键字和 __NAMESPACE__ 魔术常量 使用命名空间 - 别名和导入 全局空间 使用命名空间 - 后备全局函数和常量 名称解析规则 Errors 异常处理 基本语法 扩展 PHP 内置的异常处理类 生成器 生成器总览 生成器语法 生成器与 Iterator 对象比较 引用的解释 引用是什么 引用不是什么 引用做什么 引用传递 引用返回 取消引用 引用定位 预定义变量 超全局变量 $GLOBALS $_GET $_POST $_COOKIE $_REQUEST $_FILES $_SESSION $_SERVER $_ENV $http_response_header $argc $argv 预定义异常 Exception ErrorException 预定义接口 Traversable Iterator IteratorAggregate ArrayAccess Serializable Closure Generator 上下文选项和参数 套接字上下文选项 HTTP 上下文选项 FTP 上下文选项 SSL 上下文选项 CURL 上下文选项 Phar 上下文选项 MongoDB 上下文选项 Context 参数 支持的协议和封装协议 file:// http:// ftp:// php:// zlib:// data:// global:// phar:// ssh2:// rar:// ogg:// expect:// "},"docs/语言参考/基本语法.html":{"url":"docs/语言参考/基本语法.html","title":"基本语法","keywords":"","body":"基本语法 PHP 标记 从 HTML 中分离 指令分隔符 注释 "},"docs/语言参考/基本语法/PHP 标记.html":{"url":"docs/语言参考/基本语法/PHP 标记.html","title":"PHP 标记","keywords":"","body":"PHP 标记 当解析一个文件时,PHP 会寻找起始标记和结束标记,也就是 和 ?> ,这告诉 PHP 开始和停止解析二者之间的代码。这种解析方式使得 PHP 可以被嵌入到各种不同的文档中去,而任何起始标记和结束标记之外的部分都会被 PHP 解析器忽略。 如果文件内容是纯 PHP 代码,最好在文件末尾删除 PHP 结束标记。这可以避免在 PHP 结束标记之后万一意外加入了空格或者换行符,会导致 PHP 开始输出这些空白,而脚本中此时并无输出的意图。 "},"docs/语言参考/基本语法/从 HTML 中分离.html":{"url":"docs/语言参考/基本语法/从 HTML 中分离.html","title":"从 HTML 中分离","keywords":"","body":"从 HTML 中分离 凡是在一对起始标记和结束标记之外的内容都会被 PHP 解析器忽略,这使得 PHP 文件可以具备混合内容。可以使 PHP 嵌入到 HTML 文档中去。 Hello, World! Hello, World! 当处于条件语句中间时,此时 PHP 解释器会根据条件判断来决定哪些输出哪些跳过。 PHP 将跳过条件语句未达成的段落,即使该段落位于 PHP 开始和结束标记之外。由于 PHP 解释器会在条件未达成时直接跳过该段条件语句块,因此 PHP 会根据条件来忽略之。要输出大段文本时,跳出 PHP 解析模式通常比将文本通过 echo 或 print 输出更有效率。 Hello, World! PHP "},"docs/语言参考/基本语法/指令分隔符.html":{"url":"docs/语言参考/基本语法/指令分隔符.html","title":"指令分隔符","keywords":"","body":"指令分隔符 PHP 需要在每个语句后用分号结束指令。 一段 PHP 代码中的结束标记隐含表示了一个分号。在一个 PHP 代码段中的最后一行可以不用分号结束。如果后面还有新行,则代码段的结束标记包含了行结束。 "},"docs/语言参考/基本语法/注释.html":{"url":"docs/语言参考/基本语法/注释.html","title":"注释","keywords":"","body":"注释 单行注释仅仅注释到行末或者当前的 PHP 代码块,视乎哪个首先出现。 多行注释在碰到第一个 */ 时结束。要确保不要嵌套多行注释,试图注释掉一大块代码时很容易出现该错误。 "},"docs/语言参考/类型.html":{"url":"docs/语言参考/类型.html","title":"类型","keywords":"","body":"类型 Boolean 布尔类型 Integer 整型 Float 浮点型 String 字符串 Array 数组 Object 对象 Resource 资源类型 NULL Callable 可调用类型 类型转换的判别 "},"docs/语言参考/类型/Boolean 布尔类型.html":{"url":"docs/语言参考/类型/Boolean 布尔类型.html","title":"Boolean 布尔类型","keywords":"","body":"Boolean 布尔类型 要指定一个布尔类型值,使用常量 true 或 false 。 通常运算符所返回的布尔类型值结果会被传递给流程控制。 转换为布尔类型: "},"docs/语言参考/类型/Integer 整型.html":{"url":"docs/语言参考/类型/Integer 整型.html","title":"Integer 整型","keywords":"","body":"Integer 整型 整型值可以使用十进制,十六进制,八进制或二进制表示,前面可以加上可选的符号 - 或者 + 。要使用十六进制表达,数字前必须加上 0x 。要使用八进制表达,数字前必须加上 0 。要使用二进制表达,数字前必须加上 0b 。 转换为整型: 注意,绝不要将未知的浮点型值强制转换为整型值,这样会导致不可预料的结果。 这是因为以十进制能够精确表示的有理数如 0.1 或 0.7 ,无论有多少尾数都不能被内部所使用的二进制精确表示,因此不能在不丢失一点精度的情况下转换为二进制的格式。 "},"docs/语言参考/类型/Float 浮点型.html":{"url":"docs/语言参考/类型/Float 浮点型.html","title":"Float 浮点型","keywords":"","body":"Float 浮点型 浮点型,也叫浮点数,双精度数或实数,可以用以下任一语法定义: 转换为浮点型: "},"docs/语言参考/类型/String 字符串.html":{"url":"docs/语言参考/类型/String 字符串.html","title":"String 字符串","keywords":"","body":"String 字符串 定义一个字符串的最简单的方法是用单引号 '' 把它包围起来。 要表达一个单引号自身,需在它的前面加个反斜线 \\ 来转义。要表达一个反斜线自身,则用两个反斜线 \\\\ 。其它任何方式的反斜线都会被当成反斜线本身。也就是说如果想使用其它转义序列例如 \\r 或者 \\n ,并不代表任何特殊含义,就单纯是这两个字符本身。 如果字符串是包围在双引号 \"\" 中, PHP 将对一些特殊的字符进行解析。 另一种表达字符串的方法是用 Heredoc 句法结构: 。在该运算符之后要提供一个标识符,然后换行。接下来是字符串本身,最后要用前面定义的标识符作为结束标志。标识符的命名也要像其它标签一样遵守 PHP 的规则:只能包含字母、数字和下划线,并且必须以字母和下划线作为开头。 Heredoc 结构就像是没有使用双引号的双引号字符串,这就是说在 Heredoc 结构中单引号不用被转义,但是转义序列还可以使用。变量将被替换,但在 Heredoc 结构中含有复杂的变量时要格外小心。 就像 Heredoc 结构类似于双引号字符串, Nowdoc 结构是类似于单引号字符串的。 Nowdoc 结构很像 Heredoc 结构,但是 Nowdoc 中不进行解析操作。这种结构很适合用于嵌入 PHP 代码或其它大段文本而无需对其中的特殊字符进行转义。一个 Nowdoc 结构也和 Heredoc 结构用一样的标记 ,但是跟在后面的标识符要用单引号括起来,即 。 Heredoc 结构的所有规则也同样适用于 Nowdoc 结构。 当 PHP 解析器遇到一个美元符号 $ 时,它会和其它很多解析器一样,去组合尽量多的标识以形成一个合法的变量名。 一个数组索引也可以被解析,数组索引要用方括号 ] 来表示索引结束的边际。 'cat', 'dog', 'bird']; var_dump(\"foo bar $foo[foo]baz qux\"); // string(18) \"foo bar catbaz qux\" var_dump(\"foo bar $foo[0] baz qux\"); // string(19) \"foo bar dog baz qux\" var_dump(\"foo bar $foo[1] baz qux\"); // string(20) \"foo bar bird baz qux\" var_dump(\"foo bar $foo[0]baz qux\"); // string(18) \"foo bar dogbaz qux\" var_dump(\"foo bar $foo[1]baz qux\"); // string(19) \"foo bar birdbaz qux\" 一个对象属性也可被解析,对象属性则是和上述的变量规则相同。 property baz qux\"); // string(19) \"foo bar foo baz qux\" var_dump(\"foo bar $foo->propertybaz qux\"); // string(12) \"foo bar qux\" 复杂语法不是因为其语法复杂而得名,而是因为它可以使用复杂的表达式。只需简单地像在字符串以外的地方那样写出表达式,然后用花括号 {} 把它括起来即可。由于 { 无法被转义,只有 $ 紧挨着 { 时才会被识别。可以用 {\\$ 来表达 {$ 。 数组索引可以使用复杂语法解析。 'cat', 'dog', 'bird']; var_dump(\"foo bar {$foo['foo']}baz qux\"); // string(18) \"foo bar catbaz qux\" var_dump(\"foo bar {$foo[0]} baz qux\"); // string(19) \"foo bar dog baz qux\" var_dump(\"foo bar {$foo[1]} baz qux\"); // string(20) \"foo bar bird baz qux\" var_dump(\"foo bar {$foo[0]}baz qux\"); // string(18) \"foo bar dogbaz qux\" var_dump(\"foo bar {$foo[1]}baz qux\"); // string(19) \"foo bar birdbaz qux\" 对象属性也可以使用复杂语法解析。 property} baz qux\"); // string(19) \"foo bar foo baz qux\" var_dump(\"foo bar {$foo->property}baz qux\"); // string(18) \"foo bar foobaz qux\" 字符串中的字符可以通过一个从 0 开始的下标,用类似数组结构中的方括号包含对应的数字来访问。 也可以用类似数组结构中的方括号包含对应的数字来修改。 字符串下标必须为整数或可转换为整数的字符串,否则会发出警告并转换成 0 。 转换为字符串: "},"docs/语言参考/类型/Array 数组.html":{"url":"docs/语言参考/类型/Array 数组.html","title":"Array 数组","keywords":"","body":"Array 数组 可以用 array() 语言结构来新建一个数组。它接受任意数量用逗号分隔的键值对。最后一个数组单元之后的逗号可以省略。 'cat', 'bar' => 'dog' ); 还可以使用短数组定义语法,用 [] 替代 array() 。 'cat', 'bar' => 'dog' ]; 数组的键名可以是整型或者字符串。数组的值可以是任意类型。 此外数组的键会有如下的强制转换: 包含有合法整型值的字符串会被转换为整型,例如键名 \"8\" 实际会被储存为 8 ,但是 \"08\" 则不会强制转换,因为其不是一个合法的十进制数值。 浮点类型也会被转换为整型,意味着其小数部分会被舍去,例如键名 8.7 实际会被储存为 8 。 布尔类型也会被转换成整型,即键名 true 实际会被储存为 1 ,而键名 false 会被储存为 0 。 NULL 会被转换为空字符串,即键名 NULL 实际会被储存为 \"\" 。 数组和对象不能被用为键名,坚持这么做会导致警告。 如果在数组定义中多个单元都使用了同一个键名,则只使用了最后一个,之前的都被覆盖了。 'foo', '1' => 'bar', 1.5 => 'baz', true => 'qux' ]; var_dump($foo); // array(1) { [1]=> string(3) \"qux\" } 如果对给出的值没有指定键名,则取当前最大的整数索引值,新的键名将是该值加一。如果指定的键名已经有了值,则该值会被覆盖。 'baz', 'qux']; var_dump($foo); // array(4) { [0]=> string(3) \"foo\" [1]=> string(3) \"bar\" [6]=> string(3) \"baz\" [7]=> string(3) \"qux\" } 可以用直接对函数或方法调用的结果进行数组解引用。 要修改数组中的某个键值,通过其键名给该单元赋一个新值。 'cat', 'bar' => 'dog' ]; $foo['bar'] = 'cat'; var_dump($foo); // array(2) { [\"foo\"]=> string(3) \"cat\" [\"bar\"]=> string(3) \"cat\" } 也可以省略键名,在这种情况下给变量名加上一对空的方括号 [] 。 'cat', 'bar' => 'dog' ]; $foo[] = 'bird'; var_dump($foo); // array(3) { [\"foo\"]=> string(3) \"cat\" [\"bar\"]=> string(3) \"dog\" [0]=> string(4) \"bird\" } 要删除某键值对,对其调用 unset() 函数。 'cat', 'bar' => 'dog' ]; unset($foo['foo']); var_dump($foo); // array(1) { [\"bar\"]=> string(3) \"dog\" } 最大整数键名不一定当前就在数组中,它只要在上次数组重新生成索引后曾经存在过就行了。 int(1) [1]=> int(2) [2]=> int(3) [3]=> int(4) [4]=> int(5) } foreach ($foo as $key => $value) { unset($foo[$key]); } var_dump($foo); // array(0) { } $foo[] = 6; var_dump($foo); // array(1) { [5]=> int(6) } $foo = array_values($foo); $foo[] = 7; var_dump($foo); // array(2) { [0]=> int(6) [1]=> int(7) } 直接改变数组的值可以通过引用传递来做到。 int(3) [1]=> int(5) [2]=> int(6) } 转换为数组: bool(true) } var_dump((array) false); // array(1) { [0]=> bool(false) } var_dump((array) 0); // array(1) { [0]=> int(0) } var_dump((array) 1); // array(1) { [0]=> int(1) } var_dump((array) 1.001); // array(1) { [0]=> float(1.001) } var_dump((array) 'foo'); // array(1) { [0]=> string(3) \"foo\" } var_dump((array) new Foo()); // array(0) { } var_dump((array) new Bar()); // array(3) { [\"public\"]=> string(6) \"public\" [\"\\0*\\0protected\"]=> string(9) \"protected\" [\"\\0Bar\\0private\"]=> NULL } "},"docs/语言参考/类型/Object 对象.html":{"url":"docs/语言参考/类型/Object 对象.html","title":"Object 对象","keywords":"","body":"Object 对象 要创建一个新的对象,使用 new 语句实例化一个类。 转换为对象: string(3) \"foo\" } var_dump((object) [2, 4, 5]); // object(stdClass)#1 (3) { [\"0\"]=> int(2) [\"1\"]=> int(4) [\"2\"]=> int(5) } var_dump((object) ['foo' => 'cat', 'bar' => 'dog']); // object(stdClass)#1 (2) { [\"foo\"]=> string(3) \"cat\" [\"bar\"]=> string(3) \"dog\" } "},"docs/语言参考/类型/Resource 资源类型.html":{"url":"docs/语言参考/类型/Resource 资源类型.html","title":"Resource 资源类型","keywords":"","body":"Resource 资源类型 资源是一种特殊变量,保存了到外部资源的一个引用。资源是通过专门的函数来建立和使用的。 "},"docs/语言参考/类型/NULL.html":{"url":"docs/语言参考/类型/NULL.html","title":"NULL","keywords":"","body":"NULL 特殊的 NULL 类型表示一个变量没有值。 NULL 类型唯一可能的值就是 NULL 。 在下列情况下一个变量被认为是 NULL : 尚未被赋值。 被赋值为 NULL 。 被 unset() 。 "},"docs/语言参考/类型/Callable 可调用类型.html":{"url":"docs/语言参考/类型/Callable 可调用类型.html","title":"Callable 可调用类型","keywords":"","body":"Callable 可调用类型 用户自定义函数。 匿名函数。 类中的普通方法。 类中的静态方法。 父类中的普通方法。 父类中的静态方法。 类中的 __invoke() 魔术方法。 "},"docs/语言参考/类型/类型转换的判别.html":{"url":"docs/语言参考/类型/类型转换的判别.html","title":"类型转换的判别","keywords":"","body":"类型转换的判别 PHP 在变量定义中不需要或不支持明确的类型定义。变量类型是根据使用该变量的上下文所决定的。也就是说,如果把一个字符串值赋给一个变量,这个变量就成了一个字符串。如果又把一个整型赋给这个变量,那它就成了一个整型。PHP 的自动类型转换的一个例子是乘法运算符 * 。如果任何一个操作数是浮点型,则所有的操作数都被当成浮点型,结果也是浮点型。 否则操作数会被解释为整型,结果也是整型。注意这并没有改变这些操作数本身的类型,改变的仅是这些操作数如何被求值以及表达式本身的类型。 当一个字符串被当作一个数值来取值,如果该字符串没有包含 . 、 e 或 E 并且其数字值在整型的范围之内,该字符串将被当成整型来取值。其它所有情况下都被作为浮点型来取值。该字符串的开始部分决定了它的值。如果该字符串以合法的数值开始,则使用该数值。否则其值为 0 。合法数值由可选的正负号,后面跟着一个或多个数字,可能有小数点,再跟着可选的指数部分。指数部分由 e 或 E 后面跟着一个或多个数字构成。 "},"docs/语言参考/变量.html":{"url":"docs/语言参考/变量.html","title":"变量","keywords":"","body":"变量 基本语法 变量范围 可变变量 来自 PHP 之外的变量 "},"docs/语言参考/变量/基本语法.html":{"url":"docs/语言参考/变量/基本语法.html","title":"基本语法","keywords":"","body":"基本语法 PHP 中的变量用一个美元符号 $ 后面跟变量名来表示。变量名是区分大小写的。变量名与 PHP 中其它的标签一样遵循相同的规则。一个有效的变量名由字母或者下划线开头,后面跟上任意数量的字母,数字,或者下划线。 以下划线开头,合法。 变量默认总是传值赋值。那也就是说,当将一个表达式的值赋予一个变量时,整个原始表达式的值被赋值到目标变量。这意味着,当一个变量的值赋予另外一个变量时,改变其中一个变量的值,将不会影响到另外一个变量。 PHP 也提供了另外一种方式给变量赋值:引用赋值。这意味着新的变量简单的引用了原始变量。改动新的变量将影响到原始变量,反之亦然。 "},"docs/语言参考/变量/变量范围.html":{"url":"docs/语言参考/变量/变量范围.html","title":"变量范围","keywords":"","body":"变量范围 变量的范围即它定义的上下文背景,也就是它的生效范围。大部分的 PHP 变量只有一个单独的范围。这个单独的范围跨度同样包含了引入的文件。 上例中的 example.php 文件内容: 在用户自定义函数中,一个局部函数范围将被引入。任何用于函数内部的变量按缺省情况将被限制在局部函数范围内。 PHP 中全局变量在函数中使用时必须将变量声明为 global ,在函数中声明了全局变量之后,对任一变量的所有引用都会指向其全局版本。 在局部函数范围内访问全局变量的第二个办法,是用特殊的 PHP 自定义 $GLOBALS 数组。 $GLOBALS 是一个关联数组,每一个变量为一个元素,键名对应变量名,值对应变量的内容。 $GLOBALS 之所以在全局范围内存在,是因为 $GLOBALS 是一个超全局变量。 变量范围的另一个重要特性是静态变量。静态变量仅在局部函数域中存在,但当程序执行离开此作用域时,其值并不丢失。 静态变量也提供了一种处理递归函数的方法。递归函数是一种调用自己的函数。写递归函数时要小心,因为可能会无穷递归下去。必须确保有充分的方法来中止递归。 "},"docs/语言参考/变量/可变变量.html":{"url":"docs/语言参考/变量/可变变量.html","title":"可变变量","keywords":"","body":"可变变量 有时候使用可变变量名是很方便的。就是说,一个变量的变量名可以动态的设置和使用。一个可变变量获取了一个普通变量的值作为这个可变变量的变量名。 要将可变变量用于数组,必须解决一个模棱两可的问题。 类的属性也可以通过可变属性名来访问。可变属性名将在该调用所处的范围内被解析。 $bar); // string(3) \"BAR\" var_dump($foo->{$baz}[2]); // string(3) \"BAZ\" var_dump($foo->{$qux[1]}); // string(3) \"BAR\" "},"docs/语言参考/变量/来自 PHP 之外的变量.html":{"url":"docs/语言参考/变量/来自 PHP 之外的变量.html","title":"来自 PHP 之外的变量","keywords":"","body":"来自 PHP 之外的变量 当一个表单提交给 PHP 脚本时,表单中的信息会自动在脚本中可用。 Login 上例中的 example.php 文件内容: 变量名中的点和空格被转换成下划线。 Submit 上例中的 example.php 文件内容: PHP 也懂得表单变量上下文中的数组。例如可以将相关的变量编成组,或者用此特性从多选输入框中取得值。 1 2 3 4 Submit 上例中的 example.php 文件内容: 当提交表单时,可以用一幅图像代替标准的提交按钮。当用户点击到图像中的某处时,相应的表单会被传送到服务器,并加上两个变量,它们包含了用户点击图像的坐标。有经验的用户可能会注意到被浏览器发送的实际变量名包含的是一个点而不是下划线,但 PHP 自动将点转换成了下划线。 上例中的 example.php 文件内容: PHP 透明地支持 RFC 6265 定义中的 HTTP Cookie 。 Cookie 是一种在浏览器端存储数据并能追踪或识别再次访问的用户的机制。可以用 setcookie() 函数设定 Cookie 。 Cookie 是 HTTP 信息头中的一部分,因此 setcookie() 函数必须在向浏览器发送任何输出之前调用。 "},"docs/语言参考/常量.html":{"url":"docs/语言参考/常量.html","title":"常量","keywords":"","body":"常量 基本语法 魔术常量 "},"docs/语言参考/常量/基本语法.html":{"url":"docs/语言参考/常量/基本语法.html","title":"基本语法","keywords":"","body":"基本语法 常量是一个简单值的标识符。如同其名称所暗示的,在脚本执行期间该值不能改变,除了所谓的魔术常量,它们其实不是常量。常量默认为大小写敏感,传统上常量标识符总是大写的。常量名和其它任何 PHP 标签遵循同样的命名规则。合法的常量名以字母或下划线开始,后面跟着任何字母,数字或下划线。如果使用了一个未定义的常量, PHP 假定想要的是该常量本身的名字,如同用字符串调用它一样。此时将发出一个 E_NOTICE 级的错误。 常量和变量有如下不同: 常量前面没有美元符号 $ 。 常量只能用 define() 函数或 const 关键字定义,而不能通过赋值语句。 常量可以不用理会变量的作用域而在任何地方定义和访问。 常量一旦定义就不能被重新定义或者取消定义。 常量的值只能是标量,数组或资源。 bool(true) [1]=> bool(false) } var_dump(QUX); // resource(4) of type (stream) 也可以使用 const 关键字定义常量,但必须处于最顶端的作用区域。 "},"docs/语言参考/常量/魔术常量.html":{"url":"docs/语言参考/常量/魔术常量.html","title":"魔术常量","keywords":"","body":"魔术常量 __LINE__ 用来获取文件中的当前行号。 __FILE__ 用来获取当前文件的完整路径和文件名。 __DIR__ 用来获取当前文件所在的目录。 __FUNCTION__ 用来获取当前函数的名称。 __CLASS__ 用来获取当前类的名称。 __TRAIT__ 用来获取当前 Trait 的名称。 __METHOD__ 用来获取当前类的方法名。 __NAMESPACE__ 用来获取当前命名空间的名称(区分大小写)。 "},"docs/语言参考/表达式.html":{"url":"docs/语言参考/表达式.html","title":"表达式","keywords":"","body":"表达式 表达式是 PHP 最重要的基石。在 PHP 中,几乎所写的任何东西都是一个表达式。 稍微复杂的表达式例子就是函数。 这里还涉及到一个额外的值,即赋值语句本身的值,赋值语句本身求值为被赋的值。 …… "},"docs/语言参考/运算符.html":{"url":"docs/语言参考/运算符.html","title":"运算符","keywords":"","body":"运算符 运算符优先级 算数运算符 赋值运算符 位运算符 比较运算符 错误控制运算符 执行运算符 递增递减运算符 逻辑运算符 字符串运算符 数组运算符 类型运算符 "},"docs/语言参考/运算符/运算符优先级.html":{"url":"docs/语言参考/运算符/运算符优先级.html","title":"运算符优先级","keywords":"","body":"运算符优先级 运算符优先级指定了两个表达式绑定得有多紧密。如果运算符优先级相同,那运算符的结合方向决定了该如何运算。没有结合的相同优先级的运算符不能连在一起使用。括号的使用,哪怕在不是必要的场合下,通过括号的配对来明确标明运算顺序,而非靠运算符优先级和结合性来决定,通常能够增加代码的可读性。下表按照优先级从高到低列出了运算符。同一行中的运算符具有相同优先级,此时它们的结合方向决定求值顺序。 结合方向 运算符 无 clone new 左 [ 右 ** 右 ++ -- ~ (int) (float) (string) (array) (object) (bool) @ 无 instanceof 右 ! 左 * / % 左 + - . 左 > 无 >= 无 == != <> === !== 左 & 左 ^ 左 | 左 && 左 || 左 ?? 左 ?: 右 = += -= *= /= %= **= .= &= |= ^= >= ??= 左 and 左 xor 左 or 算数运算符是左联的。 赋值运算符是右联的。 递增运算符优先级高于算数运算符和赋值运算符。 "},"docs/语言参考/运算符/算数运算符.html":{"url":"docs/语言参考/运算符/算数运算符.html","title":"算数运算符","keywords":"","body":"算数运算符 取反运算符 - 返回一个数的负值。 加法运算符 + 返回两个数相加的和。 减法运算符 - 返回两个数相减的差。 乘法运算符 * 返回两个数相乘的积。 除法运算符 / 总是返回浮点数。只有在两个操作数都是整数(或字符串转换成的整数)并且正好能整除,这时它返回一个整数。 取模运算符 % 的操作数在运算之前都会转换成整数(除去小数部分)。取模运算符 % 的结果和被除数的符号(正负号)相同。 幂运算符 ** 返回一个数指定次方的幂。 "},"docs/语言参考/运算符/赋值运算符.html":{"url":"docs/语言参考/运算符/赋值运算符.html","title":"赋值运算符","keywords":"","body":"赋值运算符 基本的赋值运算符是 = 。它意味着把右边表达式的值赋给左边的运算数。注意赋值运算将原变量的值拷贝到新变量中(传值赋值),所以改变其中一个并不影响另一个。在 PHP 中普通的传值赋值行为有个例外就是碰到对象时,在 PHP 中是以引用赋值的。 PHP 支持引用赋值,引用赋值意味着两个变量指向了同一个数据,没有拷贝任何东西。 "},"docs/语言参考/运算符/位运算符.html":{"url":"docs/语言参考/运算符/位运算符.html","title":"位运算符","keywords":"","body":"位运算符 按位与运算符 & 把两个数中都为 1 的位设为 1 。 (00000000 00000000 00000000 00000000) => int(0) var_dump(2 & 5); // (00000000 00000000 00000000 00000010) & (00000000 00000000 00000000 00000101) => (00000000 00000000 00000000 00000000) => int(0) var_dump(-4 & 5); // (11111111 11111111 11111111 11111100) & (00000000 00000000 00000000 00000101) => (00000000 00000000 00000000 00000100) => int(4) var_dump(-8 & -5); // (11111111 11111111 11111111 11111000) & (11111111 11111111 11111111 11111011) => (11111111 11111111 11111111 11111000) => int(-8) $foo = -8; // (11111111 11111111 11111111 11111000) $bar = -5; // (11111111 11111111 11111111 11111011) $foo &= $bar; // (11111111 11111111 11111111 11111000) var_dump($foo); // int(-8) 按位或运算符 | 把两个数中任何一个为 1 的位设为 1 。 (00000000 00000000 00000000 00000101) => int(5) var_dump(2 | 5); // (00000000 00000000 00000000 00000010) | (00000000 00000000 00000000 00000101) => (00000000 00000000 00000000 00000111) => int(7) var_dump(-4 | 5); // (11111111 11111111 11111111 11111100) | (00000000 00000000 00000000 00000101) => (11111111 11111111 11111111 11111101) => int(-3) var_dump(-8 | -5); // (11111111 11111111 11111111 11111000) | (11111111 11111111 11111111 11111011) => (11111111 11111111 11111111 11111011) => int(-5) $foo = -8; // (11111111 11111111 11111111 11111000) $bar = -5; // (11111111 11111111 11111111 11111011) $foo |= $bar; // (11111111 11111111 11111111 11111011) var_dump($foo); // int(-5) 按位异或运算符 ^ 把两个数中一个为 1 另一个为 0 的位设为 1 。 (00000000 00000000 00000000 00000101) => int(5) var_dump(2 ^ 5); // (00000000 00000000 00000000 00000010) ^ (00000000 00000000 00000000 00000101) => (00000000 00000000 00000000 00000111) => int(7) var_dump(-4 ^ 5); // (11111111 11111111 11111111 11111100) ^ (00000000 00000000 00000000 00000101) => (11111111 11111111 11111111 11111001) => int(-7) var_dump(-8 ^ -5); // (11111111 11111111 11111111 11111000) ^ (11111111 11111111 11111111 11111011) => (00000000 00000000 00000000 00000011) => int(3) $foo = -8; // (11111111 11111111 11111111 11111000) $bar = -5; // (11111111 11111111 11111111 11111011) $foo ^= $bar; // (00000000 00000000 00000000 00000011) var_dump($foo); // int(3) 按位取反运算符 ~ 把一个数中为 0 的位设为 1 ,为 1 的位设为 0 。 (11111111 11111111 11111111 11111111) => int(-1) var_dump(~2); // (00000000 00000000 00000000 00000010) => (11111111 11111111 11111111 11111101) => int(-3) var_dump(~-4); // (11111111 11111111 11111111 11111100) => (00000000 00000000 00000000 00000011) => int(3) var_dump(~-8); // (11111111 11111111 11111111 11111000) => (00000000 00000000 00000000 00000111) => int(7) 按位左移运算符 把一个数的位向左移动指定的位数。左移时右侧以零填充,符号位被移走意味着正负号不被保留。 (00000000 00000000 00000000 00000000) => int(0) var_dump(2 (00000000 00000000 00000000 00001000) => int(8) var_dump(-4 (11111111 11111111 11111111 11110000) => int(-16) var_dump(-8 (11111111 11111111 11111111 11100000) => int(-32) $foo = -8; // (11111111 11111111 11111111 11111000) $foo 按位右移运算符 >> 把一个数的位向右移动指定的位数。右移时左侧以符号位填充,意味着正负号被保留。 > 2); // (00000000 00000000 00000000 00000000) => (00000000 00000000 00000000 00000000) => int(0) var_dump(2 >> 2); // (00000000 00000000 00000000 00000010) => (00000000 00000000 00000000 00000000) => int(0) var_dump(-4 >> 2); // (11111111 11111111 11111111 11111100) => (11111111 11111111 11111111 11111111) => int(-1) var_dump(-8 >> 2); // (11111111 11111111 11111111 11111000) => (11111111 11111111 11111111 11111110) => int(-2) $foo = -8; // (11111111 11111111 11111111 11111000) $foo >>= 2; // (11111111 11111111 11111111 11111110) var_dump($foo); // int(-2) "},"docs/语言参考/运算符/比较运算符.html":{"url":"docs/语言参考/运算符/比较运算符.html","title":"比较运算符","keywords":"","body":"比较运算符 等于运算符 == 返回两个值类型转换后是否相等。如果比较一个数字和字符串或者比较涉及到数字内容的字符串,则字符串会被转换为数值并且比较按照数值来进行。 以上规则同样也适用于 switch 语句。 全等运算符 === 返回两个值的类型和数值是否相等。 不等运算符 != 返回两个值类型转换后是否不等。 不全等运算符 !== 返回两个值的类型或数值是否不等。 小于运算符 返回一个值是否严格小于另一个值。 大于运算符 > 返回一个值是否严格大于另一个值。 3); // bool(false) var_dump(10 > 3); // bool(true) var_dump('foo' > 3); // bool(false) var_dump('0010' > 3); // bool(true) 小于等于运算符 返回一个值是否小于或等于另一个值。 大于等于运算符 >= 返回一个值是否大于或等于另一个值。 = 3); // bool(true) var_dump(10 >= 3); // bool(true) var_dump('foo' >= 3); // bool(false) var_dump('0010' >= 3); // bool(true) 太空船运算符(组合比较符) 当一个值小于、等于、大于另一个值时分别返回一个小于、等于、大于 0 的整数。 1); // int(0) var_dump(2 1); // int(1) var_dump(1 2); // int(-1) var_dump('foo' 'foo'); // int(0) var_dump('foo' 'bar'); // int(1) var_dump('bar' 'foo'); // int(-1) var_dump([] []); // int(0) var_dump([2, 4, 5] [2, 4, 5]); // int(0) var_dump([2, 4, 5] [2, 4, 4]); // int(1) var_dump([2, 4, 4] [2, 4, 5]); // int(-1) var_dump(['foo' => 'cat'] ['foo' => 'cat']); // int(0) var_dump(['foo' => 'dog'] ['foo' => 'cat']); // int(1) var_dump(['foo' => 'cat'] ['foo' => 'dog']); // int(-1) var_dump(['foo' => 'cat', 'bar' => 'dog'] ['foo' => 'cat']); // int(1) var_dump(['foo' => 'cat'] ['bar' => 'dog']); // int(1) $foo = (object)['foo' => 'cat']; $bar = (object)['foo' => 'cat']; var_dump($foo $bar); // int(0) $foo = (object)['foo' => 'dog']; $bar = (object)['foo' => 'cat']; var_dump($foo $bar); // int(1) $foo = (object)['foo' => 'cat']; $bar = (object)['foo' => 'dog']; var_dump($foo $bar); // int(-1) $foo = (object)['foo' => 'cat']; $bar = (object)['bar' => 'dog']; var_dump($foo $bar); // int(1) 另一个条件运算符是 ?: (或三元运算符)。 表达式一 ? 表达式二 : 表达式三 在表达式一求值为 true 的时候值为表达式二,在表达式一求值为 false 的时候值为表达式三。建议避免将三元运算符堆积在一起使用。当在一条语句中使用多个三元运算符时会造成 PHP 运算结果不清晰。 可以省略三元运算符中间那部分。 表达式一 ?: 表达式二 在表达式一求值为 true 时返回表达式一,否则返回表达式二。 NULL 合并操作符 ?? 返回从左往右第一个存在且不为 NULL 的操作数。如果都没有定义且不为 NULL,则返回 NULL 。 "},"docs/语言参考/运算符/错误控制运算符.html":{"url":"docs/语言参考/运算符/错误控制运算符.html","title":"错误控制运算符","keywords":"","body":"错误控制运算符 PHP 支持一个错误控制运算符 @ 。当将其放置在一个 PHP 表达式之前,该表达式可能产生的任何错误信息都被忽略掉。目前的错误控制运算符 @ 甚至使导致脚本终止的严重错误的错误报告也失效。这意味着如果在某个不存在或者敲错了字母的函数调用前用了 @ 来抑制错误信息,那脚本会没有任何迹象显示原因而死在那里。 "},"docs/语言参考/运算符/执行运算符.html":{"url":"docs/语言参考/运算符/执行运算符.html","title":"执行运算符","keywords":"","body":"执行运算符 PHP 支持一个执行运算符 ` 。注意这不是单引号! PHP 将尝试将反引号中的内容作为 Shell 命令来执行,并将其输出信息返回,即可以赋给一个变量而不是简单地丢弃到标准输出。使用执行运算符 ` 的效果与 shell_exec() 函数相同。 "},"docs/语言参考/运算符/递增递减运算符.html":{"url":"docs/语言参考/运算符/递增递减运算符.html","title":"递增递减运算符","keywords":"","body":"递增递减运算符 前递增运算符和后递增运算符对于变量而言,结果都是变量的值加一。 前递增运算符首先将变量的值加一,然后返回当前的变量。 后递增运算符首先返回当前的变量,然后将变量的值加一。 递增运算符优先级高于算数运算符和赋值运算符。 前递减运算符和后递减运算符对于变量而言,结果都是变量的值减一。 前递减运算符首先将变量的值减一,然后返回当前的变量。 后递减运算符首先返回当前的变量,然后将变量的值减一。 递减运算符优先级高于算数运算符和赋值运算符。 "},"docs/语言参考/运算符/逻辑运算符.html":{"url":"docs/语言参考/运算符/逻辑运算符.html","title":"逻辑运算符","keywords":"","body":"逻辑运算符 逻辑与运算符有两种不同的形式,逻辑与运算符 && 优先级高于赋值运算符,逻辑与运算符 and 优先级低于赋值运算符。逻辑与运算符在两个值都为 true 时返回 true 。 逻辑或运算符有两种不同的形式,逻辑或运算符 || 优先级高于赋值运算符,逻辑或运算符 or 优先级低于赋值运算符。逻辑或运算符在两个值任何一个为 true 时返回 true 。 逻辑异或运算符 xor 优先级低于赋值运算符。逻辑异或运算符 xor 当一个值为 true 另一个值为 false 时返回 true 。 逻辑非运算符 ! 当一个值为 true 时返回 false , 当一个值为 false 时返回 true 。 "},"docs/语言参考/运算符/字符串运算符.html":{"url":"docs/语言参考/运算符/字符串运算符.html","title":"字符串运算符","keywords":"","body":"字符串运算符 连接运算符 . 返回其左右参数连接后的字符串。 连接赋值运算符 .= 将右边参数附加到左边的参数之后。 "},"docs/语言参考/运算符/数组运算符.html":{"url":"docs/语言参考/运算符/数组运算符.html","title":"数组运算符","keywords":"","body":"数组运算符 联合运算符 + 把右边的数组元素附加到左边的数组后面,两个数组中都有的键名,则只用左边数组中的,右边的被忽略。 int(2) [1]=> int(4) [2]=> int(5) } $foo = ['foo' => 'cat', 'bar' => 'dog']; $bar = ['foo' => '2', 'bar' => '04', 'baz' => '05']; var_dump($foo + $bar); // array(3) { [\"foo\"]=> string(3) \"cat\" [\"bar\"]=> string(3) \"dog\" [\"baz\"]=> string(2) \"05\" } $foo = ['foo' => 'cat', 'bar' => 'dog']; $bar = ['foo' => '2', 'bar' => '04', 'baz' => '05']; var_dump($bar + $foo); // array(3) { [\"foo\"]=> string(1) \"2\" [\"bar\"]=> string(2) \"04\" [\"baz\"]=> string(2) \"05\" } 等于运算符 == 在两个数组具有相同的键值对时返回 true 。 'cat', 'bar' => 'dog']; $bar = ['cat', 'dog']; var_dump($foo == $bar); // bool(false) $foo = ['foo' => 'cat', 'bar' => 'dog']; $baz = ['foo' => 0, 'bar' => 'dog']; var_dump($foo == $baz); // bool(true) 全等运算符 === 在两个数组具有相同的键值对并且顺序和类型都相同时返回 true 。 'cat', 'bar' => 'dog']; $bar = ['foo' => 0, 'bar' => 'dog']; var_dump($foo === $bar); // bool(false) $foo = ['foo' => 'cat', 'bar' => 'dog']; $baz = ['bar' => 'dog', 'foo' => 'cat']; var_dump($foo === $baz); // bool(false) 不等运算符 != 在两个数组不具有相同的键值对时返回 true 。 'cat', 'bar' => 'dog']; $bar = ['cat', 'dog']; var_dump($foo != $bar); // bool(true) $foo = ['foo' => 'cat', 'bar' => 'dog']; $baz = ['foo' => 0, 'bar' => 'dog']; var_dump($foo != $baz); // bool(false) 不全等运算符 !== 在两个数组不具有相同的键值对或顺序和类型不相同时返回 true 。 'cat', 'bar' => 'dog']; $bar = ['foo' => 0, 'bar' => 'dog']; var_dump($foo !== $bar); // bool(true) $foo = ['foo' => 'cat', 'bar' => 'dog']; $baz = ['bar' => 'dog', 'foo' => 'cat']; var_dump($foo !== $bar); // bool(true) "},"docs/语言参考/运算符/类型运算符.html":{"url":"docs/语言参考/运算符/类型运算符.html","title":"类型运算符","keywords":"","body":"类型运算符 检测一个变量是否是某个类的实例。 检测一个变量是否不是某个类的实例。 检测一个变量是否是继承自某个父类的子类的实例。 检测一个变量是否是实现某个接口的实例。 检测一个变量是否是某个对象或字符串变量的实例。 如果被检测的变量不是对象,则并不发出任何错误信息而是返回 false 。 "},"docs/语言参考/流程控制.html":{"url":"docs/语言参考/流程控制.html","title":"流程控制","keywords":"","body":"流程控制 if else elseif while do-while for foreach switch break continue 流程控制的替代语法 declare return require include require_once include_once goto "},"docs/语言参考/流程控制/if.html":{"url":"docs/语言参考/流程控制/if.html","title":"if","keywords":"","body":"if if 结构是很多语言包括 PHP 在内最重要的特性之一,它允许按照条件执行代码片段。 if 语句可以无限层地嵌套在其它 if 语句中,这给程序的不同部分的条件执行提供了充分的弹性。 "},"docs/语言参考/流程控制/else.html":{"url":"docs/语言参考/流程控制/else.html","title":"else","keywords":"","body":"else 经常需要在满足某个条件时执行一条语句,而在不满足该条件时执行其它语句,这正是 else 的功能。 else 延伸了 if 语句,可以在 if 语句中的表达式的值为 false 时执行语句。 "},"docs/语言参考/流程控制/elseif.html":{"url":"docs/语言参考/流程控制/elseif.html","title":"elseif","keywords":"","body":"elseif 和 else 一样, elseif 延伸了 if 语句,可以在原来的 if 表达式值为 false 时执行不同语句。但是和 else 不一样的是,它仅在 elseif 的条件表达式值为 true 时执行语句。在同一个 if 语句中可以有多个 elseif 部分,其中第一个表达式值为 true (如果有的话)的 elseif 部分将会执行。 elseif 的语句仅在之前的 if 和所有之前 elseif 的表达式值为 false ,并且当前的 elseif 表达式值为 true 时执行。 "},"docs/语言参考/流程控制/while.html":{"url":"docs/语言参考/流程控制/while.html","title":"while","keywords":"","body":"while while 语句的含意很简单,它告诉 PHP 只要 while 表达式的值为 true 就重复执行嵌套中的循环语句。表达式的值在每次开始循环时检查,所以即使这个值在循环语句中改变了,语句也不会停止执行,直到本次循环结束。有时候如果 while 表达式的值一开始就是 false ,则循环语句一次都不会执行。 "},"docs/语言参考/流程控制/do-while.html":{"url":"docs/语言参考/流程控制/do-while.html","title":"do-while","keywords":"","body":"do-while do-while 循环和 while 循环非常相似,区别在于表达式的值是在每次循环结束时检查而不是开始时。 和一般的 while 循环主要的区别是 do-while 的循环语句保证会执行一次(表达式的真值在每次循环结束后检查),然而在一般的 while 循环中就不一定了(表达式真值在循环开始时检查,如果一开始就为 false 则整个循环立即终止)。 "},"docs/语言参考/流程控制/for.html":{"url":"docs/语言参考/流程控制/for.html","title":"for","keywords":"","body":"for for 循环是 PHP 中最复杂的循环结构。第一个表达式在循环开始前无条件求值(并执行)一次。第二个表达式在每次循环开始前求值。如果值为 true ,则继续循环,执行嵌套的循环语句。如果值为 false ,则终止循环。第三个表达式在每次循环之后被求值(并执行)。 第二个表达式为空意味着将无限循环下去。 10) { break; } } 每个表达式都可以为空。 10) { break; } $i++; } 每个表达式都可以包括逗号分隔的多个表达式。第二个表达式中,所有用逗号分隔的表达式都会计算,但只取最后一个结果。 由于数组的长度始终不变,可以用一个中间变量来储存数组长度以优化而不是不停调用 count() 。 "},"docs/语言参考/流程控制/foreach.html":{"url":"docs/语言参考/流程控制/foreach.html","title":"foreach","keywords":"","body":"foreach foreach 语法结构提供了遍历数组的简单方式。 foreach 仅能够应用于数组和对象,如果尝试应用于其他数据类型的变量,或者未初始化的变量将发出错误信息。第一种格式遍历给定的数组。每次循环中,当前单元的值被赋给 $value 并且数组内部的指针向前移一步(因此下一次循环中将会得到下一个单元)。 第二种格式做同样的事,只除了当前单元的键名也会在每次循环中被赋给变量 $key 。 $value) { // } 可以通过引用来修改数组的元素。 int(3) [1]=> int(5) [2]=> int(6) } 还可以通过嵌套 foreach 语法结构来遍历多维数组。 PHP 可以遍历一个数组的并且把多维数组解包到循环变量中,只需将 list() 作为值提供。 "},"docs/语言参考/流程控制/switch.html":{"url":"docs/语言参考/流程控制/switch.html","title":"switch","keywords":"","body":"switch switch 语句类似于具有同一个表达式的一系列 if 语句。很多场合下需要把同一个变量(或表达式)与很多不同的值比较,并根据它等于哪个值来执行不同的代码。这正是 switch 语句的用途。如果比较一个数字和字符串或者比较涉及到数字内容的字符串,则字符串会被转换为数值并且比较按照数值来进行。 为避免错误,理解 switch 是怎样执行的非常重要。 switch 语句一行接一行地执行(实际上是语句接语句)。开始时没有代码被执行。仅当一个 case 语句中的值和 switch 表达式的值匹配时 PHP 才开始执行语句,直到 switch 的程序段结束或者遇到第一个 break 语句为止。如果不在 case 的语句段最后写上 break 的话, PHP 将继续执行下一个 case 中的语句段。 在一个 case 中的语句也可以为空,这样只不过将控制转移到了下一个 case 中的语句。 一个 case 的特例是 default 。它匹配了任何和其它 case 都不匹配的情况。 "},"docs/语言参考/流程控制/break.html":{"url":"docs/语言参考/流程控制/break.html","title":"break","keywords":"","body":"break break 在循环结构中用来结束当前循环结构的执行。它可以接受一个可选的数字参数来决定跳出几重循环。默认值是 1 ,即结束当前循环结构的执行。 break 结束当前 for 结构的执行。 break 结束当前 foreach 结构的执行。 break 结束当前 while 结构的执行。 break 结束当前 do-while 结构的执行。 break 结束当前 switch 结构的执行。 "},"docs/语言参考/流程控制/continue.html":{"url":"docs/语言参考/流程控制/continue.html","title":"continue","keywords":"","body":"continue continue 在循环结构中用来跳过本次循环中剩余的代码并在条件求值为真时开始执行下一次循环。它可以接受一个可选的数字参数来决定跳过几重循环到循环结尾。默认值是 1 ,即跳到当前循环末尾。 continue 跳过当前 for 结构的执行。 continue 跳过当前 foreach 结构的执行。 continue 跳过当前 while 结构的执行。 continue 跳过当前 do-while 结构的执行。 continue 跳过当前 switch 结构的执行。 "},"docs/语言参考/流程控制/流程控制的替代语法.html":{"url":"docs/语言参考/流程控制/流程控制的替代语法.html","title":"流程控制的替代语法","keywords":"","body":"流程控制的替代语法 PHP 提供了一些流程控制的替代语法。下面是 if 的替代语法。 替代语法同样可以用在 else 中,下面是一个包括 else 的 if 结构用替代语法格式写的例子。 替代语法同样可以用在 elseif 中,下面是一个包括 elseif 的 if 结构用替代语法格式写的例子。 while 的替代语法。 for 的替代语法。 foreach 的替代语法。 switch 的替代语法。 "},"docs/语言参考/流程控制/declare.html":{"url":"docs/语言参考/流程控制/declare.html","title":"declare","keywords":"","body":"declare Tick (时钟周期)是一个在 declare 代码段中解释器每执行 N 条可计时的低级语句就会发生的事件。 N 的值是在 declare 中用 ticks = N 来指定的。不是所有语句都可计时。通常条件表达式和参数表达式都不可计时。在每个 Tick 中出现的事件是由 register_tick_function() 来指定的。注意每个 Tick 中可以出现多个事件。 0) { $foo += 2; } // string(3) \"foo\" // string(3) \"foo\" // string(3) \"foo\" 默认情况下,如果能做到的话, PHP 将会强迫错误类型的值转为函数期望的标量类型。 例如,一个函数的一个参数期望是字符串,但传入的是整型,最终函数得到的将会是一个字符串类型的值。可以基于每一个文件开启严格模式。在严格模式中,只有一个与类型声明完全相符的变量才会被接受,否则将会抛出一个 TypeError 。 唯一的一个例外是可以将整型传给一个期望浮点数的函数。使用 declare 语句和 strict_types 声明来启用严格模式。启用严格模式同时也会影响返回值类型声明。严格类型适用于在启用严格模式的文件内的函数调用,而不是在那个文件内声明的函数。 一个没有启用严格模式的文件内调用了一个在启用严格模式的文件中定义的函数,那么将会遵循调用者的偏好(弱类型),而这个值将会被转换。 "},"docs/语言参考/流程控制/return.html":{"url":"docs/语言参考/流程控制/return.html","title":"return","keywords":"","body":"return 如果在一个函数中调用 return 语句,将立即结束此函数的执行并将它的参数作为函数的值返回。 如果在全局范围中调用,则当前脚本文件中止运行。如果当前脚本文件是被 require 的或者 include 的,则控制交回调用文件。此外,如果当前脚本是被 require 的或者 include 的,则 return 的值会被当作 require 或 include 调用的返回值。如果在主脚本文件中调用 return ,则脚本中止运行。 上例中的 example.php 文件内容: "},"docs/语言参考/流程控制/require.html":{"url":"docs/语言参考/流程控制/require.html","title":"require","keywords":"","body":"require require 语句包含并运行指定文件。被包含文件先按参数给出的路径寻找,如果没有给出目录(只有文件名)时则按照 include_path 指定的目录寻找。如果在 include_path 下没找到该文件则 require 最后才在调用脚本文件所在的目录和当前工作目录下寻找。如果最后仍未找到文件则 require 会发出一个致命错误。 如果定义了路径,不管是绝对路径(在 Windows 下以盘符或者 \\ 开头,在 Unix / Linux 下以 / 开头)还是当前目录的相对路径(以 . 或者 .. 开头), include_path 都会被完全忽略。例如一个文件以 ../ 开头,则解析器会在当前目录的父目录下寻找该文件。 当一个文件被包含时,其中所包含的代码继承了 require 所在行的变量范围。从该处开始,调用文件在该行处可用的任何变量在被调用的文件中也都可用。不过所有在包含文件中定义的函数和类都具有全局作用域。 上例中的 example.php 文件内容: 如果 require 出现于调用文件中的一个函数里,则被调用的文件中所包含的所有代码将表现得如同它们是在该函数内部定义的一样。所以它将遵循该函数的变量范围。 上例中的 example.php 文件内容: 在失败时 require 发出一个致命错误。成功的包含则返回 1 ,除非在包含文件中另外给出了返回值。 上例中的 foo.php 文件内容: 上例中的 bar.php 文件内容: "},"docs/语言参考/流程控制/include.html":{"url":"docs/语言参考/流程控制/include.html","title":"include","keywords":"","body":"include include 语句包含并运行指定文件。被包含文件先按参数给出的路径寻找,如果没有给出目录(只有文件名)时则按照 include_path 指定的目录寻找。如果在 include_path 下没找到该文件则 include 最后才在调用脚本文件所在的目录和当前工作目录下寻找。如果最后仍未找到文件则 include 会发出一条警告。 如果定义了路径,不管是绝对路径(在 Windows 下以盘符或者 \\ 开头,在 Unix / Linux 下以 / 开头)还是当前目录的相对路径(以 . 或者 .. 开头), include_path 都会被完全忽略。例如一个文件以 ../ 开头,则解析器会在当前目录的父目录下寻找该文件。 当一个文件被包含时,其中所包含的代码继承了 include 所在行的变量范围。从该处开始,调用文件在该行处可用的任何变量在被调用的文件中也都可用。不过所有在包含文件中定义的函数和类都具有全局作用域。 上例中的 example.php 文件内容: 如果 include 出现于调用文件中的一个函数里,则被调用的文件中所包含的所有代码将表现得如同它们是在该函数内部定义的一样。所以它将遵循该函数的变量范围。 上例中的 example.php 文件内容: 在失败时 include 返回 false 并且发出警告。成功的包含则返回 1 ,除非在包含文件中另外给出了返回值。 上例中的 foo.php 文件内容: 上例中的 bar.php 文件内容: "},"docs/语言参考/流程控制/require_once.html":{"url":"docs/语言参考/流程控制/require_once.html","title":"require_once","keywords":"","body":"require_once require_once 语句和 require 语句完全相同,唯一区别是 PHP 会检查该文件是否已经被包含过,如果是则不会再次包含。 require_once 可以用于在脚本执行期间同一个文件有可能被包含超过一次的情况下,想确保它只被包含一次以避免函数重定义,变量重新赋值等问题。 "},"docs/语言参考/流程控制/include_once.html":{"url":"docs/语言参考/流程控制/include_once.html","title":"include_once","keywords":"","body":"include_once include_once 语句和 include 语句完全相同,唯一区别是 PHP 会检查该文件是否已经被包含过,如果是则不会再次包含。 include_once 可以用于在脚本执行期间同一个文件有可能被包含超过一次的情况下,想确保它只被包含一次以避免函数重定义,变量重新赋值等问题。 "},"docs/语言参考/流程控制/goto.html":{"url":"docs/语言参考/流程控制/goto.html","title":"goto","keywords":"","body":"goto goto 操作符可以用来跳转到程序中的另一位置。该目标位置可以用目标名称加上冒号来标记,而跳转指令是 goto 之后接上目标位置的标记。 PHP 中的 goto 有一定限制,目标位置只能位于同一个文件和作用域,也就是说无法跳出一个函数或类方法,也无法跳入到另一个函数。也无法跳入到任何循环或者 switch 结构中。 可以跳出循环或者 switch ,通常的用法是用 goto 代替多层的 break 。 "},"docs/语言参考/函数.html":{"url":"docs/语言参考/函数.html","title":"函数","keywords":"","body":"函数 用户自定义函数 函数的参数 返回值 可变函数 匿名函数 "},"docs/语言参考/函数/用户自定义函数.html":{"url":"docs/语言参考/函数/用户自定义函数.html","title":"用户自定义函数","keywords":"","body":"用户自定义函数 任何有效的 PHP 代码都有可能出现在函数内部,甚至包括其它函数和类定义。函数名和 PHP 中的其它标识符命名规则相同。有效的函数名以字母或下划线打头,后面跟字母,数字或下划线。 函数无需在调用之前被定义,除非函数是有条件被定义的。当一个函数是有条件被定义时,必须在调用函数之前定义。 函数中的函数。 递归函数。 "},"docs/语言参考/函数/函数的参数.html":{"url":"docs/语言参考/函数/函数的参数.html","title":"函数的参数","keywords":"","body":"函数的参数 类型声明允许函数在调用时要求参数为特定类型。 如果给出的值类型不对,那么将会产生一个错误。为了指定一个类型声明,类型应该加到参数名前。这个声明可以通过将参数的默认值设为 NULL 来实现允许传递 NULL 。 类型 描述 类/接口名称 参数必须是给定的类或实现接口的实例 self 参数必须是与定义方法的类相同的实例 array 参数必须是数组 callable 参数必须是可调用类型 bool 参数必须是布尔类型 float 参数必须是浮点型 int 参数必须是整型 string 参数必须是字符串 默认情况下,函数参数通过值传递(因而即使在函数内部改变参数的值,它并不会改变函数外部的值)。 int(2) [1]=> int(4) [2]=> int(5) } 如果希望允许函数修改它的参数值,必须通过引用传递参数。 int(2) [2]=> int(5) } PHP 还允许使用数组和特殊类型 NULL 作为默认参数。默认值必须是常量表达式,不能是诸如变量,类成员,或者函数调用等。注意当使用默认参数时,任何默认参数必须放在任何非默认参数的右侧。否则,函数将不会按照预期的情况工作。 基本类参数类型声明。 基本接口参数类型声明。 默认情况下,如果能做到的话, PHP 将会强迫错误类型的值转为函数期望的标量类型。 例如,一个函数的一个参数期望是字符串,但传入的是整型,最终函数得到的将会是一个字符串类型的值。可以基于每一个文件开启严格模式。在严格模式中,只有一个与类型声明完全相符的变量才会被接受,否则将会抛出一个 TypeError 。 唯一的一个例外是可以将整型传给一个期望浮点数的函数。使用 declare 语句和 strict_types 声明来启用严格模式。启用严格模式同时也会影响返回值类型声明。严格类型适用于在启用严格模式的文件内的函数调用,而不是在那个文件内声明的函数。 一个没有启用严格模式的文件内调用了一个在启用严格模式的文件中定义的函数,那么将会遵循调用者的偏好(弱类型),而这个值将会被转换。 PHP 在用户自定义函数中支持可变数量的参数列表。参数列表可能包含 ... 标记,表示该函数接受可变数量的参数。参数将作为数组传递给给定变量。 还可以使用 ... 在调用函数时将数组或 Traversable 变量或文字解压缩到参数列表中。 "},"docs/语言参考/函数/返回值.html":{"url":"docs/语言参考/函数/返回值.html","title":"返回值","keywords":"","body":"返回值 与参数类型声明类似 ,返回类型声明指定将从函数返回的值的类型。 返回类型声明可以使用相同的类型。 类型 描述 类/接口名称 返回值必须是给定的类或实现接口的实例 self 返回值必须是与定义方法的类相同的实例 array 返回值必须是数组 callable 返回值必须是可调用类型 bool 返回值必须是布尔类型 float 返回值必须是浮点型 int 返回值必须是整型 string 返回值必须是字符串 值通过使用可选的返回语句返回。可以返回包括数组和对象的任意类型。返回语句会立即中止函数的运行,并且将控制权交回调用该函数的代码行。如果省略了 return ,则返回值为 NULL 。 返回一个数组以得到多个返回值。 从函数返回一个引用。 property; } } $foo = new Foo(); $property = &$foo->method(); var_dump($property); // int(5) $foo->property = 6; var_dump($property); // int(6) 基本类返回类型声明。 基本接口返回类型声明。 严格类型也会对返回类型声明产生影响。在严格模式下,返回的值必须是指定的类型,否则将引发 TypeError 。 在默认的弱类型下,如果返回的值不是指定的类型,则它将被强制转换为正确的类型。 "},"docs/语言参考/函数/可变函数.html":{"url":"docs/语言参考/函数/可变函数.html","title":"可变函数","keywords":"","body":"可变函数 PHP 支持可变函数的概念。这意味着如果一个变量名后有圆括号, PHP 将寻找与变量的值同名的函数,并且尝试执行它。可变函数可以用来实现包括回调函数,函数表在内的一些用途。 可以用可变函数的语法来调用一个对象的方法。 $method(); 也可以用可变函数的语法来调用一个对象的静态属性和静态方法。 还可以调用存储在变量中的任何可调用对象。 调用类中的 __invoke 魔术方法。 "},"docs/语言参考/函数/匿名函数.html":{"url":"docs/语言参考/函数/匿名函数.html","title":"匿名函数","keywords":"","body":"匿名函数 匿名函数,也叫闭包函数,允许临时创建一个没有指定名称的函数。最经常用作回调函数参数的值。当然,也有其它应用的情况。匿名函数目前是通过 Closure 类来实现的。 闭包函数也可以作为变量的值来使用。 PHP 会自动把此种表达式转换成内置类 Closure 的对象实例。把一个 Closure 对象赋值给一个变量的方式与普通变量赋值的语法是一样的。 闭包函数可以从父作用域中继承变量, 任何此类变量都应该用 use 语言结构传递进去。 从父作用域中继承的变量的值取决于闭包函数被定义的时候,而不是被调用的时候。 闭包函数也可以从父作用域中继承变量的引用。 在类的上下文中声明时,当前类自动绑定到它,使得在函数范围内可以使用 $this 。 method(); var_dump($method()); // object(Foo)#1 (0) { } 如果不需要当前类的自动绑定,则可以使用静态匿名函数。 method(); var_dump($method()); // PHP Fatal error: Uncaught Error: Using $this when not in object context. PHP 还支持短闭包来实现更简洁的单行书写。 strtoupper($matches[1]), 'foo' ); var_dump($foo); // string(3) \"FOO\" 短闭包可以直接访问闭包函数外部的变量,所以不需要再使用 use 关键词。 strtoupper($string); var_dump($foo()); // string(3) \"FOO\" "},"docs/语言参考/类与对象.html":{"url":"docs/语言参考/类与对象.html","title":"类与对象","keywords":"","body":"类与对象 基本语法 属性 类常量 类的自动加载 构造函数和析构函数 访问控制 对象继承 范围解析操作符 Static 关键字 抽象类 对象接口 Trait 匿名类 重载 遍历对象 魔术方法 Final 关键字 对象复制 对象比较 类型约束 后期静态绑定 对象和引用 对象序列化 "},"docs/语言参考/类与对象/基本语法.html":{"url":"docs/语言参考/类与对象/基本语法.html","title":"基本语法","keywords":"","body":"基本语法 每个类的定义都以关键字 class 开头,后面跟着类名,后面跟着一对花括号,里面包含有类的属性与方法的定义。类名可以是任何非 PHP 保留字的合法标签。一个合法类名以字母或下划线开头,后面跟着若干字母,数字或下划线。一个类可以包含有属于自己的常量,变量(属性)以及函数(方法)。 当一个方法在类定义内部被调用时,有一个可用的伪变量 $this 。 $this 是一个到主叫对象的引用(通常是该方法所从属的对象,但如果是从第二个对象静态调用时也可能是另一个对象)。 property; } } $foo = new Foo(); var_dump($foo->method()); // string(3) \"foo\" 要创建一个类的实例,必须使用 new 关键字。当创建新对象时该对象总是被赋值,除非该对象定义了构造函数并且在出错时抛出了一个异常。类应在被实例化之前定义(某些情况下则必须这样)。如果在 new 之后跟着的是一个包含有类名的字符串,则该类的一个实例被创建。如果该类属于一个命名空间,则必须使用其完整名称。 在类定义内部,可以用 new self 创建新对象。 在类定义内部,可以用 new parent 创建新对象。 在类定义内部,可以用 new static 创建新对象。 当把一个对象已经创建的实例赋给一个新变量时,新变量会访问同一个实例,就和用该对象赋值一样。 可以通过一个表达式来访问新创建对象的成员。 property); // string(3) \"foo\" 类中的属性和方法存在于单独的“名称空间”中,因此可以使用具有相同名称的属性和方法。 test); // string(8) \"property\" var_dump($foo->test()); // string(6) \"method\" 调用存储在属性中的匿名函数。 property = function (): string { return 'foo'; }; } } $foo = new Foo(); $method = $foo->property; var_dump($method()); // string(3) \"foo\" var_dump(($foo->property)()); // string(3) \"foo\" 一个类可以在声明中用 extends 关键字继承另一个类的方法和属性。 PHP 不支持多重继承,一个类只能继承一个基类。被继承的方法和属性可以通过用同样的名字重新声明来覆盖。但是如果父类定义方法时使用了 final ,则该方法不可被覆盖。可以通过 parent:: 来访问被覆盖的方法或属性。当覆盖方法时,参数必须保持一致否则 PHP 将发出 E_STRICT 级别的错误信息。但构造函数例外,构造函数可在被覆盖时使用不同的参数。 method()); // string(3) \"bar\" 关键字 class 也可用于类名的解析。使用关键字 class 可以获取一个字符串,包含了类的完全限定名称。这对使用了命名空间的类尤其有用。 "},"docs/语言参考/类与对象/属性.html":{"url":"docs/语言参考/类与对象/属性.html","title":"属性","keywords":"","body":"属性 类的变量成员叫做属性。属性声明是由关键字 public , protected 或者 private 开头,然后跟一个普通的变量声明来组成。属性中的变量可以初始化,但是初始化的值必须是常数,这里的常数是指 PHP 脚本在编译阶段时就可以得到其值,而不依赖于运行时的信息才能求值。在类的成员方法里面,可以用对象运算符 $this->property 这种方式来访问非静态属性。静态属性则是用范围解析操作符 self::$property 来访问。 foo); // int(5) var_dump($foo->bar); // string(3) \"bar\" var_dump($foo->baz); // array(2) { [0]=> bool(true) [1]=> bool(false) } var_dump($foo->qux); // resource(4) of type (stream) "},"docs/语言参考/类与对象/类常量.html":{"url":"docs/语言参考/类与对象/类常量.html","title":"类常量","keywords":"","body":"类常量 可以把在当前类中始终保持不变的值定义为常量。在定义和使用常量的时候不需要使用美元符号 $ 。常量的值必须是一个常数。可以用一个变量来动态调用类。但该变量的值不能为关键字(如 self , parent 或 static )。 bool(true) [1]=> bool(false) } $foo = new Foo(); $foo = new $foo; var_dump($foo::QUX); // resource(4) of type (stream) 类常量与常量不同的是,类常量可以被子类重写。 "},"docs/语言参考/类与对象/类的自动加载.html":{"url":"docs/语言参考/类与对象/类的自动加载.html","title":"类的自动加载","keywords":"","body":"类的自动加载 在编写面向对象程序时,很多开发者为每个类新建一个 PHP 文件。 这会带来一个烦恼:每个脚本的开头,都需要包含一个长长的列表(每个类都有一个文件)。使用 spl_autoload_register() 函数可以注册任意数量的自动加载器,当使用尚未被定义的类和接口时自动去加载。通过注册自动加载器,脚本引擎在 PHP 出错失败前有了最后一个机会加载所需的类。 上例中的 Foo.php 文件内容: 上例中的 Bar.php 文件内容: "},"docs/语言参考/类与对象/构造函数和析构函数.html":{"url":"docs/语言参考/类与对象/构造函数和析构函数.html","title":"构造函数和析构函数","keywords":"","body":"构造函数和析构函数 PHP 允许开发者在一个类中定义一个方法作为构造函数。具有构造函数的类会在每次创建新对象时先调用此方法,所以非常适合在使用对象之前做一些初始化工作。 property = 'foo'; } } $foo = new Foo(); var_dump($foo->property); // string(3) \"foo\" 如果子类中定义了构造函数则不会隐式调用其父类的构造函数。要执行父类的构造函数,需要在子类的构造函数中调用 parent::__construct() 。如果子类没有定义构造函数则会如同一个普通的类方法一样从父类继承(假如没有被定义为 private 的话)。 property = 'foo'; } } class Bar { /** * Override the parent constructor. * * @param void * @return void */ public function __construct() { $this->property = 'bar'; } } class Baz extends Foo { /** * Call the parent constructor. * * @param void * @return void */ public function __construct() { parent::__construct(); } } class Qux extends Foo { // } $foo = new Foo(); var_dump($foo->property); // string(3) \"foo\" $bar = new Bar(); var_dump($bar->property); // string(3) \"bar\" $baz = new Baz(); var_dump($baz->property); // string(3) \"foo\" $qux = new Qux(); var_dump($qux->property); // string(3) \"foo\" PHP 引入了析构函数的概念,析构函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行。 和构造函数一样,父类的析构函数不会被引擎暗中调用。要执行父类的析构函数,必须在子类的析构函数体中显式调用 parent::__destruct() 。此外也和构造函数一样,子类如果自己没有定义析构函数则会继承父类的。析构函数即使在使用 exit() 终止脚本运行时也会被调用。在析构函数中调用 exit() 将会中止其余关闭操作的运行。 "},"docs/语言参考/类与对象/访问控制.html":{"url":"docs/语言参考/类与对象/访问控制.html","title":"访问控制","keywords":"","body":"访问控制 对属性或方法的访问控制,是通过在前面添加关键字 public (公有), protected (受保护)或 private (私有)来实现的。被定义为公有的类成员可以在任何地方被访问。被定义为受保护的类成员则可以被其自身以及其子类和父类访问。被定义为私有的类成员则只能被其定义所在的类访问。 $this->public, 'protected' => $this->protected, 'private' => $this->private ]; } } $foo = new Foo(); var_dump($foo->public); // string(6) \"public\" var_dump($foo->protected); // PHP Fatal error: Uncaught Error: Cannot access protected property Foo::$protected. var_dump($foo->private); // PHP Fatal error: Uncaught Error: Cannot access private property Foo::$private. var_dump($foo->method()); // array(3) { [\"public\"]=> string(6) \"public\" [\"protected\"]=> string(9) \"protected\" [\"private\"]=> string(7) \"private\" } 可以对 public 属性和 protected 属性进行覆盖,但 private 属性不能。 $this->public, 'protected' => $this->protected, 'private' => $this->private ]; } } $bar = new Bar(); var_dump($bar->public); // string(6) \"public\" var_dump($bar->protected); // PHP Fatal error: Uncaught Error: Cannot access protected property Bar::$protected. var_dump($bar->private); // NULL var_dump($bar->method()); // array(3) { [\"public\"]=> string(6) \"public\" [\"protected\"]=> string(3) \"bar\" [\"private\"]=> NULL } 类中的方法可以被定义为公有,私有或受保护。如果没有设置这些关键字,则该方法默认为公有。 $this->public(), 'protected' => $this->protected(), 'private' => $this->private() ]; } } $foo = new Foo(); var_dump($foo->public()); // string(6) \"public\" var_dump($foo->protected()); // PHP Fatal error: Uncaught Error: Call to protected method Foo::protected() from context ''. var_dump($foo->private()); // PHP Fatal error: Uncaught Error: Call to private method Foo::private() from context ''. var_dump($foo->method()); // array(3) { [\"public\"]=> string(6) \"public\" [\"protected\"]=> string(9) \"protected\" [\"private\"]=> string(7) \"private\" } 可以对 public 方法和 protected 方法进行覆盖,但 private 方法不能。 $this->public(), 'protected' => $this->protected(), 'private' => $this->private() ]; } } $bar = new Bar(); var_dump($bar->public()); // string(6) \"public\" var_dump($bar->protected()); // PHP Fatal error: Uncaught Error: Call to protected method Bar::protected() from context ''. var_dump($bar->private()); // PHP Fatal error: Uncaught Error: Call to private method Foo::private() from context ''. var_dump($bar->method()); // PHP Fatal error: Uncaught Error: Call to private method Foo::private() from context 'Bar'. 更多的例子。 public()); var_dump($this->private()); } } class Bar extends Foo { /** * Override the parent method. * * @param void * @return string */ public function public(): string { return 'Bar::public'; } /** * Private method. * * @param void * @return string */ private function private(): string { return 'Bar::private'; } } $bar = new Bar(); $bar->method(); // string(11) \"Bar::public\" // string(12) \"Foo::private\" 同一个类的对象即使不是同一个实例也可以互相访问对方的私有与受保护成员。这是由于在这些对象的内部具体实现的细节都是已知的。 property = $value; } /** * Change the specified property of the specified class. * * @param Foo $instance * @return string */ public function method(Foo $instance): string { return $instance->property = 'bar'; } } $foo = new Foo('foo'); var_dump($foo->method(new Foo('bar'))); // string(3) \"bar\" "},"docs/语言参考/类与对象/对象继承.html":{"url":"docs/语言参考/类与对象/对象继承.html","title":"对象继承","keywords":"","body":"对象继承 PHP 的对象模型也使用了继承。继承将会影响到类与类,对象与对象之间的关系。比如,当扩展一个类,子类就会继承父类所有公有的和受保护的方法。除非子类覆盖了父类的方法,否则被继承的方法都会保留其原有功能。继承对于功能的设计和抽象是非常有用的,而且对于类似的对象增加新功能就无须重新再写这些公用的功能。 method()); // string(3) \"foo\" var_dump($foo->test()); // string(4) \"test\" $bar = new Bar(); var_dump($bar->method()); // string(3) \"bar\" var_dump($bar->test()); // string(4) \"test\" "},"docs/语言参考/类与对象/范围解析操作符.html":{"url":"docs/语言参考/类与对象/范围解析操作符.html","title":"范围解析操作符","keywords":"","body":"范围解析操作符 范围解析操作符,或者更简单地说是一对冒号,可以用于访问静态成员,类常量,还可以用于覆盖类中的属性和方法。当在类定义之外引用到这些项目时,要使用类名。也可以通过变量来引用类,但该变量的值不能是关键字(如 self , parent 和 static )。 self , parent 和 static 这三个特殊的关键字是用于在类定义的内部对其属性或方法进行访问的。 static()); // string(3) \"FOO\" var_dump($bar->self()); // string(3) \"BAR\" var_dump($bar->parent()); // string(3) \"FOO\" var_dump($bar->static()); // string(3) \"BAR\" 当一个子类覆盖其父类中的方法时, PHP 不会调用父类中已被覆盖的方法。是否调用父类的方法取决于子类。这种机制也作用于构造函数和析构函数,重载以及魔术方法。 method()); // string(3) \"foo\" "},"docs/语言参考/类与对象/Static 关键字.html":{"url":"docs/语言参考/类与对象/Static 关键字.html","title":"Static 关键字","keywords":"","body":"Static 关键字 声明类属性或方法为静态,就可以不实例化类而直接访问。静态属性不能通过一个类已实例化的对象来访问(但静态方法可以)。由于静态方法不需要通过对象即可调用,所以伪变量 $this 在静态方法中不可用。静态属性不可以由对象运算符 -> 来访问。用静态方式调用一个非静态方法会导致一个 E_STRICT 级别的错误。就像其它所有的 PHP 静态变量一样,静态属性只能被初始化为常数。可以用一个变量来动态调用类,但该变量的值不能为关键字 self , parent 或 static 。 调用静态方法。 "},"docs/语言参考/类与对象/抽象类.html":{"url":"docs/语言参考/类与对象/抽象类.html","title":"抽象类","keywords":"","body":"抽象类 PHP 支持抽象类和抽象方法。定义为抽象的类不能被实例化。任何一个类,如果它里面至少有一个方法是被声明为抽象的,那么这个类就必须被声明为抽象的。被定义为抽象的方法只是声明了其调用方式(参数),不能定义其具体的功能实现。继承一个抽象类的时候,子类必须定义父类中的所有抽象方法。另外,这些方法的访问控制必须和父类中一样(或者更为宽松)。例如某个抽象方法被声明为受保护的,那么子类中实现的方法就应该声明为受保护的或者公有的,而不能定义为私有的。此外方法的调用方式必须匹配,即类型和所需参数数量必须一致。如果子类定义了一个可选参数,而父类抽象方法的声明里没有,则两者的声明并无冲突。 method('bar')); // string(3) \"bar\" var_dump($bar->test()); // string(3) \"foo\" $baz = new Baz(); var_dump($baz->method('baz')); // string(3) \"baz\" var_dump($baz->test()); // string(3) \"baz\" 抽象类中也可以定义常量。抽象类中的常量和类常量的使用完全相同,也可以被子类重写。 "},"docs/语言参考/类与对象/对象接口.html":{"url":"docs/语言参考/类与对象/对象接口.html","title":"对象接口","keywords":"","body":"对象接口 使用接口,可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容。接口是通过 interface 关键字来定义的,就像定义一个标准的类一样,但其中定义所有的方法都是空的。接口中定义的所有方法都必须是公有,这是接口的特性。要实现一个接口,使用 implements 操作符。类中必须实现接口中定义的所有方法,必须使用和接口中所定义的方法完全一致的方式,否则会报一个致命错误。 method('bar')); // string(3) \"bar\" $baz = new Baz(); var_dump($baz->method('baz')); // string(3) \"baz\" 接口也可以继承,通过使用 extends 操作符。 类可以实现多个接口,用逗号来分隔多个接口的名称。实现多个接口时,接口中的方法不能有重名。 接口中也可以定义常量。接口中的常量和类常量的使用完全相同,但是不能被子类或子接口所重写。 "},"docs/语言参考/类与对象/Trait.html":{"url":"docs/语言参考/类与对象/Trait.html","title":"Trait","keywords":"","body":"Trait PHP 实现了一种代码复用的方法,称为 Trait 。 Trait 是为类似 PHP 的单继承语言而准备的一种代码复用机制。 Trait 为了减少单继承语言的限制,使开发人员能够自由地在不同层次结构内独立的类中复用方法。 Trait 和类组合的语义定义了一种减少复杂性的方式,避免传统多继承和 Mixin 类相关典型问题。 Trait 和类相似,但仅仅旨在用细粒度和一致的方式来组合功能。无法通过 Trait 自身来实例化。它为传统继承增加了水平特性的组合,也就是说,应用的几个类之间不需要继承。 method()); // string(3) \"foo\" $baz = new Baz(); var_dump($baz->method()); // string(3) \"foo\" 从基类继承的成员会被 Trait 插入的成员所覆盖。优先顺序是来自当前类的成员覆盖了 Trait 的方法,而 Trait 则覆盖了被继承的方法。 method()); // string(3) \"bar\" $qux = new Qux(); var_dump($qux->method()); // string(3) \"baz\" 在一个类中使用多个 Trait。 foo()); // string(3) \"foo\" var_dump($baz->bar()); // string(3) \"bar\" 如果两个 Trait 都插入了一个同名的方法,如果没有明确解决冲突将会产生一个致命错误。为了解决多个 Trait 在同一个类中的命名冲突,需要使用 insteadof 操作符来明确指定使用冲突方法中的哪一个。以上方式仅允许排除掉其它方法, as 操作符可以 为某个方法引入别名。 注意, as 操作符不会对方法进行重命名,也不会影响其方法。 method()); // string(3) \"foo\" $qux = new Qux(); var_dump($qux->method()); // string(3) \"bar\" var_dump($qux->test()); // string(3) \"bar\" 使用 as 关键字还可以用来调整方法的访问控制。 method()); // string(3) \"foo\" $baz = new Baz(); var_dump($baz->method()); // PHP Fatal error: Uncaught Error: Call to protected method Baz::method() from context '' var_dump($baz->test()); // string(3) \"foo\" 正如类能够使用 Trait 一样,其它 Trait 也能够使用 Trait 。在 Trait 定义时通过使用一个或多个 Trait ,能够组合其它 Trait 中的部分或全部成员。 foo()); // string(3) \"foo\" var_dump($qux->bar()); // string(3) \"bar\" 为了对使用的类施加强制要求, Trait 支持抽象方法的使用。 method()); // string(3) \"bar\" Trait 方法中的静态变量。 Trait 中的静态方法。 Trait 中同样可以定义属性。 Trait 定义了一个属性后,类就不能定义同样名称的属性,否则会产生致命错误。 有种情况例外:属性是兼容的(同样的访问可见度、初始默认值)。 "},"docs/语言参考/类与对象/匿名类.html":{"url":"docs/语言参考/类与对象/匿名类.html","title":"匿名类","keywords":"","body":"匿名类 匿名类很有用,可以创建一次性的简单对象。 string(3) \"foo\" } var_dump($foo->property); // string(3) \"foo\" 可以传递参数到匿名类的构造器,也可以扩展其他类,实现接口,以及像其他普通的类一样使用 Trait 。 string(3) \"foo\" } var_dump($qux->method('qux')); // string(3) \"qux\" var_dump($qux->test()); // string(3) \"baz\" 匿名类被嵌套进普通类后,不能在匿名类中访问这个外部类的 private 、 protected 方法或者属性。为了访问外部类 protected 属性或方法,匿名类可以 extends 此外部类。 为了使用外部类的 private 属性,必须通过构造函数传进来。 bar) extends Foo { /** * Just a test property. * * @var int */ private int $baz; /** * Initialize the value of the property. * * @param int * @return void */ public function __construct(int $value) { $this->baz = $value; } /** * Calculate the sum of all expressions. * * @param void * @return int */ public function test(): int { return $this->foo + $this->baz + $this->method(); } }; } } $foo = new Foo(); var_dump($foo->call()->test()); // int(6) 声明的同一个匿名类,所创建的对象都是这个类的实例。 "},"docs/语言参考/类与对象/重载.html":{"url":"docs/语言参考/类与对象/重载.html","title":"重载","keywords":"","body":"重载 PHP 所提供的重载是指动态地创建类属性和方法。是通过魔术方法来实现的。当调用当前环境下未定义或不可见的类属性或方法时,重载方法会被调用。所有的重载方法都必须被声明为 public 。传统的重载是用于提供多个同名的类方法,但各方法的参数类型和个数不同。 在给不可访问属性赋值时, __set() 会被调用。 $name = $value; } } $foo = new Foo(); $foo->property = 'foo'; var_dump($foo->property); // string(3) \"foo\" 读取不可访问属性的值时, __get() 会被调用。 $name; } } $foo = new Foo(); var_dump($foo->property); // string(3) \"foo\" 当对不可访问属性调用 isset() 或 empty() 时, __isset() 会被调用。 $name); } } $foo = new Foo(); var_dump(isset($foo->property)); // bool(true) 当对不可访问属性调用 unset() 时, __unset() 会被调用。 $name); } /** * Unset the specified property. * * @param string $name * @return void */ public function __unset(string $name) { unset($this->$name); } } $foo = new Foo(); var_dump(isset($foo->property)); // bool(true) unset($foo->property); var_dump(isset($foo->property)); // bool(false) 在对象中调用一个不可访问方法时, __call() 会被调用。 method('foo', 'bar')); // string(14) \"method+foo+bar\" 在静态上下文中调用一个不可访问方法时, __callStatic() 会被调用。 "},"docs/语言参考/类与对象/遍历对象.html":{"url":"docs/语言参考/类与对象/遍历对象.html","title":"遍历对象","keywords":"","body":"遍历对象 PHP 提供了一种定义对象的方法使其可以通过单元列表来遍历,例如用 foreach 语句。默认情况下,所有可见属性都将被用于遍历。 $value) { var_dump(\"$key => $value\"); } } } $foo = new Foo(); foreach ($foo as $key => $value) { var_dump(\"$key => $value\"); } // string(16) \"public => public\" $foo->method(); // string(16) \"public => public\" // string(22) \"protected => protected\" // string(18) \"private => private\" 更进一步,可以实现 Iterator 接口。可以让对象自行决定如何遍历以及每次遍历时那些值可用。 property = $array; } /** * Return the current element of the specified property. * * @param void * @return int */ public function current(): int { var_dump(__METHOD__); return current($this->property); } /** * Advance the internal pointer of the specified property. * * @param void * @return void */ public function next() { var_dump(__METHOD__); next($this->property); } /** * Return the current key of the specified property. * * @param void * @return int */ public function key(): int { var_dump(__METHOD__); return key($this->property); } /** * Return the validity of the current position of the specified property. * * @param void * @return bool */ public function valid(): bool { var_dump(__METHOD__); return current($this->property) !== false; } /** * Set the internal pointer of the specified property to the first element. * * @param void * @return void */ public function rewind() { var_dump(__METHOD__); reset($this->property); } } $foo = new Foo([2, 4, 5]); foreach ($foo as $key => $value) { var_dump(\"$key => $value\"); echo \"\\r\\n\"; } // string(11) \"Foo::rewind\" // string(10) \"Foo::valid\" // string(12) \"Foo::current\" // string(8) \"Foo::key\" // string(6) \"0 => 2\" // string(9) \"Foo::next\" // string(10) \"Foo::valid\" // string(12) \"Foo::current\" // string(8) \"Foo::key\" // string(6) \"1 => 4\" // string(9) \"Foo::next\" // string(10) \"Foo::valid\" // string(12) \"Foo::current\" // string(8) \"Foo::key\" // string(6) \"2 => 5\" // string(9) \"Foo::next\" // string(10) \"Foo::valid\" 可以用 IteratorAggregate 接口以替代实现所有的 Iterator 方法。 IteratorAggregate 只需要实现一个方法 getIterator() ,其应返回一个实现了 Iterator 的类的实例。 $value) { var_dump(\"$key => $value\"); } // string(10) \"foo => foo\" // string(10) \"bar => bar\" // string(10) \"baz => baz\" // string(10) \"qux => qux\" "},"docs/语言参考/类与对象/魔术方法.html":{"url":"docs/语言参考/类与对象/魔术方法.html","title":"魔术方法","keywords":"","body":"魔术方法 __construct() , __destruct() , __call() , __callStatic() , __get() , __set() , __isset() , __unset() , __sleep() , __wakeup() , __toString() , __invoke() , __set_state() , __clone() 和 __debugInfo() 等方法在 PHP 中被称为魔术方法。 PHP 允许开发者在一个类中定义一个方法作为构造函数。具有构