├── .gitignore ├── CONTRIBUTING.md ├── FORMATTING.md ├── LICENSE ├── README.md └── specifications ├── 00-语言规范目录.md ├── 01-简介.md ├── 02-约定.md ├── 03-术语与定义.md ├── 04-基础概念.md ├── 05-类型.md ├── 06-常量.md ├── 07-变量.md ├── 08-类型转换.md ├── 09-文法结构.md ├── 10-表达式.md ├── 11-语句.md ├── 12-原生数组.md ├── 13-函数.md ├── 14-类.md ├── 15-接口.md ├── 16-类扩展特性.md ├── 17-异常处理.md ├── 18-命名空间.md ├── 19-文法定义.md └── 20-参考引用.md /.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polarphp/langspecs/7bad1deb2306fb1f24e8f8a140c5a74bfd82e1b8/.gitignore -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing to the Specification for PHP 2 | 3 | We'd love your help in improving, correcting, adding to the specification. 4 | Please [file an issue](https://github.com/php/php-langspec/issues) 5 | or [submit a pull request](https://github.com/php/php-langspec/pulls). 6 | 7 | ## Generated content 8 | 9 | The grammar listings and table of contents of the specification are automatically 10 | generated. If you want to change the grammar, you need to modify the respective 11 | ` 99 | 100 |
101 | str-numeric:: 102 | str-whitespaceopt signopt str-number 103 | 104 | str-whitespace:: 105 | str-whitespaceopt str-whitespace-char 106 | 107 | str-whitespace-char:: 108 | new-line 109 | Space character (U+0020) 110 | Horizontal-tab character (U+0009) 111 | Vertical-tab character (U+000B) 112 | Form-feed character (U+000C) 113 | 114 | str-number:: 115 | digit-sequence 116 | floating-literal 117 |118 | 119 | 120 | 请注意 *digit-sequence* 被解释为 base-10 (故 `"0377"` 被视为377十进制,具有冗余前导零,而不是八进制377). 121 | 122 | 只能对字符串执行一次变异操作,偏移量分配,这涉及简单赋值操作符 [ =](10-expressions.md#simple-assignment). 123 | 124 | 库函数 [`is_string`](http://www.php.net/is_string) 判断是否具有类型字符串。 125 | 126 | ### null 空类型 127 | 128 | null类型只有一个可能的值, [`NULL`](06-constants.md#core-predefined-constants). 此类型的表示及其值未指定。 129 | 130 | 函数 [`is_null`](http://www.php.net/is_null) 判断给定值是否为 `NULL`. 131 | 132 | ## 复合类型 133 | 134 | ### array 数组 135 | 136 | 数组是一个数据结构,包含零个或多个元素的集合,其值可通过类型`int`或 键访问`string`。查看更多详情访问 [arrays](12-arrays.md#arrays). 137 | 138 | 函数库 [`is_array`](http://www.php.net/is_array) 用来判断给定值是否为数组 139 | 140 | ### Objects 对象 141 | 142 | 一个 *object* 是一个实例的类[class](14-classes.md#classes). 每个不同的类声明 143 | [*class-declaration*](14-classes.md#class-declarations) 定义一个新的class 类类型, 每个类类型都是一个对象类型。对象类型的表示未指定。 144 | 145 | 函数 [`is_object`](http://www.php.net/is_object) 判断给定值是否为对象。 146 | 函数 [`get_class`](http://php.net/manual/function.get-class.php) 获取对象类的名称。 147 | 148 | ### Resources 149 | 一个 [*resource*](http://php.net/manual/language.types.resource.php)是一个描述某种外部实体的,示例包括文件,数据库和网络套接字。 150 | 151 | `resource` 是一个抽象实体,它表示未指定。resource 仅由具体实现创建或使用,它永远不会被PHP代码创建或使用。 152 | 每个不同的`resource`都具有某种未指定形式的唯一标识。 153 | 154 | 函数 [`is_resource`](http://www.php.net/is_resource) 用来判是否为一个 `resource` 。 155 | 函数 [`get_resource_type`](http://php.net/manual/function.get-resource-type.php) 用来获取 `resource` 的类型 156 | 157 | -------------------------------------------------------------------------------- /specifications/06-常量.md: -------------------------------------------------------------------------------- 1 | # 常量 2 | 3 | ## 概述 4 | 5 | 常量是指定的值。 一旦定义, 则常数的值不可改变。 6 | 7 | 常数的定义有两种方式: 一是使用常量声明的方法,二是通过调用函数'define'进行定义常量。 8 | 9 | - 如果'define'能够定义给定的名称,则返回' TRUE ';否则,返回FALSE。 10 | 11 | 常量只能保存符合数据类型的参数,常量也可以存储数组。 12 | 此时给定常量的名称,常量存储的参数数据类型为字符串,那么当使用定义过的常量名称时, 13 | 那么library函数将返回一个给定常量的值,此时这个常量的名称指向为定义存储于常量当中的值。 14 | 15 | ### 常量的上下文 16 | 17 | 下面的定义的常量有时也被称为魔术常量,对所有脚本自动可用,它们的值不是固定的,而且不区分大小写: 18 | 19 | | 常量名称 | 描述 | 20 | | -------------------------- | ------------------------------------------------------------ | 21 | | `__CLASS__` | `string`; 当前类的名称。在trait方法内部,使用这个trait的类的名字。如果当前名称空间不是默认名称空间,那么名称空间名称和' \ '将按此顺序提前。如果在所有类之外使用,该值就是空字符串。 | 22 | | `__COMPILER_HALT_OFFSET__` | `int`; 当使用[' __halt_compiler(); '](04-basic- concepations .md#__halt_compiler)构造时,这个常量包含源文件中紧跟在该文件中的' __halt_compiler(); '标记之后的字节偏移量. | 23 | | `__DIR__` | `string`; 返回当前脚本的目录名。只对根目录追加目录分隔符. | 24 | | `__FILE__` | `string`; 返回当前执行PHP脚本的完整路径和文件名,包含一个绝对路径. | 25 | | `__FUNCTION__` | `string`; 在函数内部进行定义, 返回定义的函数名称,如果该名称存在命名空间,则该名称后面跟着'\\'如果在函数外使用,则返回空字符串 | 26 | | `__LINE__` | `int`; 返回当前源文件的代码行数. | 27 | | `__METHOD__` | `string`; 在方法内部进行定义,返回当前定义类名后跟'::'方法的名称,并且如果存在命名空间,则返回内容后跟'\\',如果在方法外使用,则返回空字符串; | 28 | | `__NAMESPACE__` | `string`; 返回当前命名空间名称的字符串,当不存在命名空间名称时,返回空字符串 . | 29 | | `__TRAIT__` | `string`; 在trait方法中使用则返回当前trait名称. 如果并未在trait方法中进行使用。则返回空字符串 | 30 | 31 | 常量名不要以 '__' 为开头,预留给未来引擎使用。 32 | 33 | ## 预定义常量 34 | 35 | 以下常量对所有脚本自动可用; 但是它们都是区分大小写的除了 `NULL`, `TRUE` 和 `FALSE`: 36 | 37 | | 常量名称 | 描述 | 38 | | -------------------------- | ------------------------------------------------------------ | 39 | | `DEFAULT_INCLUDE_PATH` | `string`; 如果在PHP.ini文件里面没有设置include_path,那么就会使用函数库内默认定义路径 | 40 | | `E_ALL` | `int`; 支持所有的错误和警告信息 | 41 | | `E_COMPILE_ERROR` | `int`; 致命编译时错误。类似E_ERROR, 但是是由Zend脚本引擎产生的。 | 42 | | `E_COMPILE_WARNING` | `int`; 编译时警告 (非致命错误)。类似 E_WARNING,但是是由Zend脚本引擎产生的. | 43 | | `E_CORE_ERROR` | `int`; 在PHP初始化启动过程中发生的致命错误。该错误类似 E_ERROR,但是是由PHP引擎核心产生的. | 44 | | `E_CORE_WARNING` | `int`; PHP初始化启动过程中发生的警告 (非致命错误) 。类似 E_WARNING,但是是由PHP引擎核心产生的. | 45 | | `E_DEPRECATED` | `int`; 运行时通知。启用后将会对在未来版本中可能无法正常工作的代码给出警告. | 46 | | `E_ERROR` | `int`; 致命的运行时错误。这类错误一般是不可恢复的情况,例如内存分配导致的问题。后果是导致脚本终止不再继续运行。. | 47 | | `E_NOTICE` | `int`;运行时通知。表示脚本遇到可能会表现为错误的情况,但是在可以正常运行的脚本里面也可能会有类似的通知。 | 48 | | `E_PARSE` | `int`; 编译时语法解析错误。解析错误仅仅由分析器产生。 | 49 | | `E_RECOVERABLE_ERROR` | `int`; 可被捕捉的致命错误。 它表示发生了一个可能非常危险的错误,但是还没有导致PHP引擎处于不稳定的状态。 如果该错误没有被用户自定义句柄捕获 (参见 [`set_error_handler`](http://www.php.net/set_error_handler)),将成为一个 E_ERROR 从而脚本会终止运行。 | 50 | | `E_STRICT` | `int`; 启用 PHP 对代码的修改建议,以确保代码具有最佳的互操作性和向前兼容性。 | 51 | | `E_USER_DEPRECATED` | `int`; 用户产生的警告信息。 类似 **E_DEPRECATED**, 但是是由用户自己在代码中使用PHP函数 [`trigger_error`](http://www.php.net/trigger_error)来产生的. | 52 | | `E_USER_ERROR` | `int`; 用户产生的错误信息。类似 **E_ERROR**, 但是是由用户自己在代码中使用PHP函数[`trigger_error`](http://www.php.net/trigger_error)来产生的. | 53 | | `E_USER_NOTICE` | `int`; 用户产生的通知信息。类似 E_NOTICE, 但是是由用户自己在代码中使用PHP函数 [`trigger_error`](http://www.php.net/trigger_error)来产生的 | 54 | | `E_USER_WARNING` | `int`; 用户产生的警告信息。类似 E_WARNING, 但是是由用户自己在代码中使用PHP函数 [`trigger_error`](http://www.php.net/trigger_error)来产生的。 | 55 | | `E_WARNING` | `int`; 运行时警告 (非致命错误)。仅给出提示信息,但是脚本不会终止运行。 | 56 | | `E_USER_DEPRECATED` | `int`; 用户产生的警告信息。 类似 E_DEPRECATED, 但是是由用户自己在代码中使用PHP函数 [`trigger_error`](http://www.php.net/trigger_error)来产生的。 | 57 | | `FALSE` | `bool`; 不区分大小写的布尔值false | 58 | | `INF` | `float`; 无穷 | 59 | | `M_1_PI` | `float`; 1/pi | 60 | | `M_2_PI` | `float`; 2/pi | 61 | | `M_2_SQRTPI` | `float`; 2/sqrt(pi) | 62 | | `M_E` | `float`; e | 63 | | `M_EULER` | `float`; Euler constant | 64 | | `M_LN10` | `float`; log_e 10 | 65 | | `M_LN2` | `float`; log_e 2 | 66 | | `M_LNPI` | `float`; log_e(pi) | 67 | | `M_LOG10E` | `float`; log_10 e | 68 | | `M_LOG2E` | `float`; log_2 e | 69 | | `M_PI` | `float`; Pi | 70 | | `M_PI_2` | `floa`t; pi/2 | 71 | | `M_PI_4` | `float`; pi/4 | 72 | | `M_SQRT1_2` | `float`; 1/sqrt(2) | 73 | | `M_SQRT2` | `float`; sqrt(2) | 74 | | `M_SQRT3` | `float`; sqrt(3) | 75 | | `M_SQRTPI` | `float`; sqrt(pi) | 76 | | `NAN` | `float`; 不是一个数字 | 77 | | `NULL` | `null`; 不区分大小写 | 78 | | `PHP_BINARY` | `string`; 执行脚本程序的php路径 | 79 | | `PHP_BINDIR` | `string`; php文件的安装位置 | 80 | | `PHP_CONFIG_FILE_PATH` | `string`; php.ini文件位置 | 81 | | `PHP_CONFIG_FILE_SCAN_DIR` | `string`; 包含其他PHP扩展相关配置文件,在启动时加载 | 82 | | `PHP_DEBUG` | `int`; 表示运行时是否启用调试 | 83 | | `PHP_EOL` | `string`; 行结束符 | 84 | | `PHP_EXTENSION_DIR` | `string`; 在运行扩展时,由library函数[`dl`](http://www.pph.net/dl)进行搜索的文件路径 | 85 | | `PHP_EXTRA_VERSION` | `string`; 当前php额外版本. | 86 | | `PHP_INT_MAX` | `int`; 整数的最大可表示值. | 87 | | `PHP_INT_MIN` | `int`; 整数的最小可表示值. | 88 | | `PHP_INT_SIZE` | `int`; 表示整数integer值的字长. | 89 | | `PHP_FLOAT_DIG` | `int`; 可以四舍五入并且不会损失精度返回的小数位数. | 90 | | `PHP_FLOAT_EPSILON` | `float`; 可表示的x+1.0不等于1.0的最小正数x. | 91 | | `PHP_FLOAT_MIN` | `float`;大于零可表示的浮点数 | 92 | | `PHP_FLOAT_MAX` | `float`; 最大可表示浮点数. | 93 | | `PHP_MAJOR_VERSION` | `int`; 当前PHP的主版本号 | 94 | | `PHP_MANDIR` | `string`; 表示安装目录在什么地方. | 95 | | `PHP_MAXPATHLEN` | `int`; 当前php支持的包括路径在内的最长文件名. | 96 | | `PHP_MINOR_VERSION` | `int`; 当前php次版本号. | 97 | | `PHP_OS` | `string`; 安装php的操作系统. | 98 | | `PHP_OS_FAMILY` | `string`; 安装php的操作系统. 可以是以下中的任何一个 'Windows', 'BSD', 'Darwin', 'Solaris', 'Linux' 'Unknown'. | 99 | | `PHP_PREFIX` | `string`; 安装php执行configure时,“--prefix”选项设置的值. | 100 | | `PHP_RELEASE_VERSION` | `int`;当前php发布版本号 | 101 | | `PHP_ROUND_HALF_DOWN` | `int`;四舍五不入向下取整 大于一半取整.ps:echo round(9.5,0,PHP_ROUND_HALF_DOWN);//9 如果值为9.6 则输出10 | 102 | | `PHP_ROUND_HALF_EVEN` | `int`; 四舍五入取整至最近偶数.ps:round(9.5,0,PHP_ROUND_HALF_EVEN); // 10 如若是6.5输出则为6 | 103 | | `PHP_ROUND_HALF_ODD` | `int`; 四舍五入取整至最近奇数.ps:round(9.5,0,PHP_ROUND_HALF_ODD); // 9 如若是6.5输出则为7 | 104 | | `PHP_ROUND_HALF_UP` | `int`; 标准四舍五入 | 105 | | `PHP_SAPI` | `string`; 当前php的服务端api. | 106 | | `PHP_SHLIB_SUFFIX` | `string`; 当前php构建平台共享库的后缀,如so(Unix)、ddl(windows) | 107 | | `PHP_SYSCONFDIR` | `string`; PHP系统配置目录. | 108 | | `PHP_VERSION` | `string`;获取当前php的版本号 ps:5.5.38(string) | 109 | | `PHP_VERSION_ID` | `int`; 获取当前php的版本号 ps:50538(int) | 110 | | `PHP_ZTS` | `int`; 指示编译器是否在启用线程安全的情况下构建。 | 111 | | `STDIN` | `resource`; 标准的输入设备 (`php://stdin`). | 112 | | `STDOUT` | `resource`; 标准的输出设备(`php://stdout`). | 113 | | `STDERR` | `resource`; 标准的错误设备 (`php://stderr`). | 114 | | `TRUE` | `bool`; 不区分大小写的布尔值 `TRUE`. | 115 | 116 | ## 用户定义常量 117 | 118 | 常量可以在函数内部定义也可以在函数外部定义,可以在类中定义也可以在接口中定义。 -------------------------------------------------------------------------------- /specifications/07-变量.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polarphp/langspecs/7bad1deb2306fb1f24e8f8a140c5a74bfd82e1b8/specifications/07-变量.md -------------------------------------------------------------------------------- /specifications/08-类型转换.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polarphp/langspecs/7bad1deb2306fb1f24e8f8a140c5a74bfd82e1b8/specifications/08-类型转换.md -------------------------------------------------------------------------------- /specifications/09-文法结构.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polarphp/langspecs/7bad1deb2306fb1f24e8f8a140c5a74bfd82e1b8/specifications/09-文法结构.md -------------------------------------------------------------------------------- /specifications/10-表达式.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polarphp/langspecs/7bad1deb2306fb1f24e8f8a140c5a74bfd82e1b8/specifications/10-表达式.md -------------------------------------------------------------------------------- /specifications/11-语句.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polarphp/langspecs/7bad1deb2306fb1f24e8f8a140c5a74bfd82e1b8/specifications/11-语句.md -------------------------------------------------------------------------------- /specifications/12-原生数组.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polarphp/langspecs/7bad1deb2306fb1f24e8f8a140c5a74bfd82e1b8/specifications/12-原生数组.md -------------------------------------------------------------------------------- /specifications/13-函数.md: -------------------------------------------------------------------------------- 1 | # 函数 2 | 3 | ## 概述 4 | 5 | 函数被调用时,调用者可以通过“参数列表”将信息传递给它,其中包含一个或者多个“参数表达式”,或者更简单的说:“参数”。“参数”在“参数列表”中的对应位置是定义在被调用的 [函数的定义](#function-definitions) 中。 6 | 7 | “无条件定义的函数”的定义是在脚本的顶层。“有条件定义的函数”的定义是在复合语句中,例如另一个函数的主体(嵌套函数)中、条件语句等。函数嵌套的层级是没有限制的。比如一个在函数体中定义了”内部函数“的”外层函数“,直到”外层函数“至少被调用一次,否则”内部函数“是不存在的。甚至,“外层函数”被调用了,如果运行时的逻辑绕过了“内部函数”的定义,那么“内部函数”仍然是不存在的。当执行流程到定义函数的点时,条件定义的函数才会存在。 8 | 9 | 任何包含 [`yield`](10-expressions.md#yield-operator) 关键字的函数称为生成器函数。 10 | 11 | **例子** 12 | 13 | ```PHP 14 | ucf1(); // 可以在 ucf1 定义前调用它 15 | function ucf1() { ... } 16 | ucf1(); // 可以在 ucf1 定义后调用它 17 | cf1(); // 错误;调用了不存在的函数 18 | $flag = TRUE; 19 | if ($flag) { function cf1() { ... } } // cf1 现在存在了 20 | if ($flag) { cf1(); } // 现在可以调用 cf1 了 21 | // ----------------------------------------- 22 | function ucf2() { function cf2() { ... } } 23 | cf2(); // 错误;调用了不存在的函数 24 | ucf2(); //cf2 现在存在了 25 | cf2(); // 所以我们可以调用 cf2 26 | ``` 27 | 28 | ## 函数调用 29 | 30 | 一个函数通过函数调用操作符 [`()`](10-expressions.md#function-call-operator) 被调用。 31 | 32 | ## 函数定义 33 | 34 | **语法** 35 | 36 | 84 | 85 |
86 | function-definition: 87 | function-definition-header compound-statement 88 | 89 | function-definition-header: 90 | function &opt name ( parameter-declaration-listopt ) return-typeopt 91 | 92 | parameter-declaration-list: 93 | simple-parameter-declaration-list 94 | variadic-declaration-list 95 | 96 | simple-parameter-declaration-list: 97 | parameter-declaration 98 | parameter-declaration-list , parameter-declaration 99 | 100 | variadic-declaration-list: 101 | simple-parameter-declaration-list , variadic-parameter 102 | variadic-parameter 103 | 104 | parameter-declaration: 105 | type-declarationopt &opt variable-name default-argument-specifieropt 106 | 107 | variadic-parameter: 108 | type-declarationopt &opt ... variable-name 109 | 110 | return-type: 111 | : type-declaration 112 | : void 113 | 114 | type-declaration: 115 | ?opt base-type-declaration 116 | 117 | base-type-declaration: 118 | array 119 | callable 120 | iterable 121 | scalar-type 122 | qualified-name 123 | 124 | scalar-type: 125 | bool 126 | float 127 | int 128 | string 129 | 130 | default-argument-specifier: 131 | = constant-expression 132 |133 | 134 | **约束** 135 | 136 | “函数定义”中的每一个参数名必须唯一。 137 | 138 | [“条件定义的函数”](#概述) 在被调用前必须存在。 139 | 140 | 构造函数、析构函数和克隆方法的“函数定义”不得包含“返回类型”。 141 | 142 | 生成器函数如果指定了返回类型,返回类型只能是 `Generator`, `Iterator` or `Traversable` 其中之一。 143 | 144 | **语义** 145 | 146 | “函数定义”定义了一个函数调用时的“函数名称”,函数名称不区分大小写。一个函数可以定义零个或者多个参数(形参),“parameter-declaration-list” 中指定了每个形参自己的 “parameter-declaration”。每个形参都有一个名称 “variable-name” 和一个可选的默认值 “default-argument-specifier”。“parameter-declaration” 中的 `&` 表示形参是引用传递而不是值传递。“函数名称”前面的 `&` 表示函数返回值是引用返回。返回值在 [`return` 语句描述](11-语句.md#the-return-statement) 中描述。 147 | 148 | 函数被调用时,如果传入的实参存在对应的形参定义,默认使用值赋值,而对于引用传递,传入的实参值会以 [引用赋值](04-basic-concepts.md#assignment) 方式 [传递](04-basic-concepts.md#argument-passing) 给函数。如果该形参没有相应的实参传入,但形参具有默认值,默认值会通过值传递或者引用传递,默认使用值赋值将默认值分配给形参。否则,如果形参没有对应的实参也没有默认值,则形参变量不存在并且也不存在相应的 [VSlot](04-basic-concepts.md#the-memory-model)。在所有可能的形参分配了初始值或者作为实参别名之后,将执行函数的主体体,*compound-statement*。执行可能会以 [`return` 语句](11-statements.md#the-return-statement) 正常 [终止](04-basic-concepts.md#program-termination),或者 [异常终止](04-basic-concepts.md#program-termination)。 149 | 150 | 每个参数都是父函数的局部变量,并且是可修改的左值。 151 | 152 | 函数定义可能在脚本的顶层,或者在任何复合语句中,在复合语句中定义的情况下,函数是 [有条件的定义](#general),或者在 [类的方法定义内部](14-classes.md#methods)。 153 | 154 | 如果定义了可变参数,提供给函数的与前面的参数不匹配的参数都作为数组元素存储在可变参数中。第一个这样的参数获得索引0,下一个参数1,以此类推。如果没有提供额外的不匹配的参数,则可变参数的值是空数组。请注意,如果想可变参数提供了类型 或/和 引用规范,它们将应用于由其捕获的每个额外参数。 155 | 156 | 默认情况下,形参将接受任意类型的实参。但是,通过指定 *type-declaration*,可以限制接受的实参类型。通过指定 `array` 使形参只接受 `array` 类型的实参。通过指定 `callable` ,只接受函数类型(见下文)的实参。通过指定 `iterable`,只有 `array` 类型或者实现了 `Traversable` 接口的对象实参才会被接受。通过指定 *限定名称*,只接受该类型或者从该类型派生的类的实例,或者仅接受直接或间接实现该接口类型的类的实例。该检查与 [`instanceof` 操作符](10-expressions.md#instanceof-operator) 相同。 157 | 158 | `callable` 伪类型接受以下几种: 159 | 160 | * 包含了在调用时已有定义的函数名称的字符串 161 | * 一个包含索引为 `0` 和 `1` 的两个元素的数组。第一个元素可以是一个字符串或者一个对象。 162 | 如果第一个元素是字符串,第二个元素必须也是字符串,值是第一个元素指定的类中的方法。 163 | 如果第一个元素是一个对象,第二个元素必须也是字符串,值是第一个方法名,该方法可以在被调用函数的上下文中由第一个元素指定的对象上调用。 164 | * 一个 [`Closure`](14-classes.md#class-closure) 类的实例。 165 | * 一个实现了 [`__invoke`](14-classes.md#method-__invoke) 方法的类的实例。 166 | 167 | 库函数 [`is_callable`](http://php.net/is_callable) 可以检查变量内容是否可以作为函数调用。 168 | 169 | 如果通过了标量类型的类型检查,则使用此标量类型约束参数。一旦检查通过,参数类型始终是指定的标量类型(如果允许 `NULL` 或为 `NULL`)。 170 | 171 | 如果一个形参有有类型定义,除非类型可以为空,否则不接受 `NULL`。如果类型以 `?` 开头或者形参的默认值为 `NULL` ,则该类型可为 `NULL`。 172 | 173 | 指定类型的形参的默认值必须是指定的类型或者 `NULL`,并且无论模式如何,都不会对默认值执行转换。 174 | 175 | ## 返回类型 176 | 177 | 如果函数定义中有 *返回类型* 定义,函数的返回值必须和定义的类型匹配,使用和形参类型检查相同的规则。返回类型不允许 `NULL` 值。如果 [`return` 语句](11-statements.md#the-return-statement) 的值未通过类型检查,则会产生致命错误。 178 | 179 | `void` 类型是一种特殊类型,只能用作返回类型,而不能用于其它上下文。它在运行时没有效果,请参见 [`return` 语句](11-statements.md#the-return-statement)。 180 | 181 | ## 类型检查模式 182 | 183 | 类型检查分为两种模式,严格模式和强制模式(默认)。只有标量类型参数(`int`, `float`, `string` 和 `bool`)在这两种不同模式下表现不同。 184 | 185 | 强制模式下,如果传递的值和参数类型相同,直接接受,如果不是,则尝试 [转换](08-conversions.md#general) ,如果转换成功,转换后的值传给参数,如果转换失败,则会出现致命错误。 186 | 187 | 严格模式下,参数必须与声明的类型完全相同(比如,`int` 类型变量不接受值为字符串 `"1"` 的值)。唯一的例外是,`int` 类型的值可以被 `float` 类型的参数接受并且会[被转为 `float`](08-conversions.md#converting-to-floating-point-type) 。 188 | 189 | 注意,如果参数是引用传递,并且发生了转换,新转换后的值会重新分配给该值。 190 | 191 | 模式由 [`declare` 语句](11-statements.md#the-declare-statement) 设置。 192 | 193 | 注意,类型检查模式是由调用者控制的,不是被调用者。在要调用的函数中执行检查时,调用者定义检查是否严格。可以使用不同上下文的严格和强制模式检查来调用相同的函数。 194 | 195 | 返回类型的检查始终由定义函数的脚本定义。 196 | 197 | **例子** 198 | 199 | ```PHP 200 | // 默认强制模式 201 | function accept_int(int $a) { return $a+1; } 202 | accept_int(1); // ok 203 | accept_int("123"); // ok 204 | accept_int("123.34"); // ok 205 | accept_int("123.34 and some"); // ok + 注意 206 | accept_int("not 123"); // 致命错误 207 | accept_int(null); // 致命错误 208 | 209 | function accept_int_or_not(int $a = null) { return $a+1; } 210 | accept_int_or_not(null); // ok 211 | 212 | function convert_int(int &$a) { return $a+1; } 213 | $a = "12"; 214 | convert_int($a); 215 | var_dump($a); // $a 现在是int类型 216 | 217 | // 现在是强制模式 218 | declare(strict_types=1); 219 | function accept_int(int $a) { return $a+1; } 220 | function accept_float(float $a) { return $a+1; } 221 | accept_int(1); // ok 222 | accept_float(1); // ok 223 | accept_int(1.5); // 致命错误 224 | accept_int("123"); // 致命错误 225 | echo substr("123", "1"); // 致命错误 226 | 227 | ``` 228 | 229 | ## 可变函数 230 | 231 | 如果一个变量后有函数调用的操作符 [`()`](10-expressions.md#function-call-operator),并且这个变量的值对应的函数在当前上下文已定义且可见(参见上面的描述),该函数会被执行。如果变量值不是有效的函数或者函数无法调用,则会产生致命错误。 232 | 233 | ## Anonymous Functions 匿名函数 234 | 235 | 匿名函数是没有函数名称定义的函数,也叫闭包函数。因此它必须在一个表达式的上下文中定义,其值可以立即调用这个函数,或者保存在变量中以便以后执行。匿名函数通过 [匿名函数创建操作符](10-expressions.md#anonymous-function-creation) 定义。 236 | 237 | [`__FUNCTION__` 和 `__METHOD__`](06-constants.md#context-dependent-constants) 获取匿名函数的名称都是 `{closure}`。 238 | -------------------------------------------------------------------------------- /specifications/14-类.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polarphp/langspecs/7bad1deb2306fb1f24e8f8a140c5a74bfd82e1b8/specifications/14-类.md -------------------------------------------------------------------------------- /specifications/15-接口.md: -------------------------------------------------------------------------------- 1 | # 接口 2 | 3 | ## 概述 4 | 5 | 类A我们称他为合同A通过所谓的接口可以实现了一组功能。接口是一个集合 6 | 方法声明和常量的。注意,这些方法是唯一的声明,而不是定义;也就是说, 接口定义了由以下内容组成的类型 7 | 抽象方法, 而客户端只在他们认为合适地方进行实现这些方法。接口允许不相关的类实现具有相同名称和类型的相同工具要求这些类共享一个公共基类. 8 | 9 | 一个接口可以扩展一个或多个其他接口,在这种情况下,它从其基本接口继承所有成员。 10 | 11 | ## 接口声明 12 | 13 | **语法** 14 | 15 | 23 | 24 |
25 | interface-declaration: 26 | interface name interface-base-clauseopt { interface-member-declarationsopt } 27 | interface-base-clause: 28 | extends qualified-name 29 | interface-base-clause , qualified-name 30 |31 | 32 | **约束** 33 | 34 | 接口不能直接或间接地从自身实现。 35 | 36 | 每个限定名必须命名一个接口类型。 37 | 38 | **语义** 39 | 40 | 接口声明定义了一个或多个类可以执行的派生。 41 | 42 | 接口名不区分大小写。 43 | 44 | 可选选项指定来自 *interface-base-clause* 的基本接口定义的接口是派生的。在这种情况下,派生接口继承来自基本接口的所有成员。 45 | 46 | **例子** 47 | 48 | ```PHP 49 | interface MyCollection 50 | { 51 | const MAX_NUMBER_ITEMS = 1000; 52 | function put($item); 53 | function get(); 54 | } 55 | class MyList implements MyCollection 56 | { 57 | public function put($item) { /* implement method */ } 58 | public function get() { /* implement method */ } 59 | ... 60 | } 61 | class MyQueue implements MyCollection 62 | { 63 | public function put($item) { /* implement method */ } 64 | public function get() { /* implement method */ } 65 | ... 66 | } 67 | function processCollection(MyCollection $p1) 68 | { 69 | ... /* can process any object whose class implements MyCollection */ 70 | } 71 | processCollection(new MyList(...)); 72 | processCollection(new MyQueue(...)); 73 | ``` 74 | 75 | ## 接口成员 76 | 77 | **语法** 78 | 79 | 88 | 89 |
90 | interface-member-declarations: 91 | interface-member-declaration 92 | interface-member-declarations interface-member-declaration 93 | 94 | interface-member-declaration: 95 | class-const-declaration 96 | method-declaration 97 |98 | 99 | * [*const-declaration*](14-classes.md#constants) 100 | * [*method-declaration*](14-classes.md#methods) 101 | 102 | **语义** 103 | 104 | 接口的成员是由*interface-member-declaration*指定的, 成员从它的基地继承 105 | 接口。 106 | 107 | 接口可以包含以下成员: 108 | 109 | - [常量](#constants) – 与接口关联的常量值。 110 | - [方法](#methods) –计算和操作的占位符由接口的实现者执行。 111 | 112 | ## 常量 113 | 114 | **约束** 115 | 116 | 接口中声明的所有常量必须是隐式或显式公开的。 117 | 118 | **语义** 119 | 120 | 接口常量就像一个类 [constant](14-classes.md#constants), 接口常量不能被实现它的类覆盖,也不能被扩展它的接口覆盖。 121 | 122 | **例子** 123 | 124 | ```PHP 125 | interface MyCollection 126 | { 127 | const MAX_NUMBER_ITEMS = 1000; 128 | function put($item); 129 | function get(); 130 | } 131 | ``` 132 | 133 | ## 方法 134 | 135 | **约束** 136 | 137 | 接口中声明的所有方法都必须是隐式或显式的它们是公开的,不能被定义为`abstract`. 138 | 139 | **语义** 140 | 141 | 接口方法就像 [abstract method](14-classes.md#methods). 142 | 143 | **例子** 144 | 145 | ```PHP 146 | interface MyCollection 147 | { 148 | const MAX_NUMBER_ITEMS = 1000; 149 | function put($item); 150 | function get(); 151 | } 152 | ``` 153 | 154 | ## 接口预定义 155 | 156 | ### 接口类 `ArrayAccess` 157 | 158 | 该接口允许使用类似数组的表示法访问实现类的实例。该接口定义如下: 159 | 160 | ```PHP 161 | interface ArrayAccess 162 | { 163 | function offsetExists($offset); 164 | function offsetGet($offset); 165 | function offsetSet($offset, $value); 166 | function offsetUnset($offset); 167 | } 168 | ``` 169 | 170 | 接口成员定义如下: 171 | 172 | | Name | Purpose | 173 | | -------------- | ------------------------------------------------------------ | 174 | | `offsetExists` | 如果实例包含键`$offset `的元素,则该实例方法返回`TRUE `,否则返回`FALSE `。 | 175 | | `offsetGet` | 这个实例方法获取键` $offset `的值。它可以通过`值`或`byRef`返回。(通常,这是不允许的,因为实现接口的类需要匹配接口的方法签名;但是,引擎对`ArrayAccess`进行了特殊处理,并允许这样做)。当实现此接口的类的实例在[subscripted](10-expressions.md#subscript-operator)非lvalue上下文中时,将调用此方法。 | 176 | | `offsetSet` | 这个实例方法将键`$offset `的值设置为$value。它不返回值。当实现此接口的类的实例在[subscripted](10-expressions.md#subscript-operator)可修改的lvalue上下文中时,将调用此方法。 | 177 | | `offsetUnset` | 这个实例方法销毁键`$offset `的值。它不返回值。 | 178 | 179 | ### 接口类 `Iterator` 180 | 181 | 该接口允许将实现类的实例作为集合处理。该接口定义如下: 182 | 183 | ```PHP 184 | interface Iterator extends Traversable 185 | { 186 | function current(); 187 | function key(); 188 | function next(); 189 | function rewind(); 190 | function valid(); 191 | } 192 | 193 | ``` 194 | 195 | 接口成员定义如下: 196 | 197 | | Name | Purpose | 198 | | --------- | ------------------------------------------------------------ | 199 | | `current` | 这个实例方法返回当前元素的位置。 | 200 | | `key` | 这个实例方法返回当前元素的键。失败时,返回' NULL ';否则,它返回键的标量值。 | 201 | | `next` | 这个实例方法将当前位置向前移动到下一个元素。它不返回值。在`foreach`语句中,该方法在每个循环之后调用。 | 202 | | `rewind` | 此实例方法将当前位置重置为第一个元素。它不返回值。在`foreach`语句中,该方法在开始时只调用一次。 | 203 | | `valid` | 这个实例方法检查当前位置是否有效。它不需要参数。它返回一个bool值为`TRUE`,表示当前位置是有效的;返回`FALSE`, 则表示为无效的。该方法在每次调用 [`Iterator::rewind()`](http://php.net/manual/iterator.rewind.php) 和 [`Iterator::next()`](http://php.net/manual/iterator.next.php)之后进行调用。 | 204 | 205 | ### 接口类 `IteratorAggregate` 206 | 207 | 该接口允许创建外部迭代器。接口定义如下: 208 | 209 | ```PHP 210 | interface IteratorAggregate extends Traversable 211 | { 212 | function getIterator(); 213 | } 214 | ``` 215 | 接口成员定义如下 216 | 217 | 218 | | Name | Purpose | 219 | | ------------- | ------------------------------------------------------------ | 220 | | `getIterator` | 这个实例方法检索一个迭代器,它实现了 `Iterator` 或 `Traversable`。 在失败时在`Exception`中抛出异常。 | 221 | 222 | ### 接口类 `Throwable` 223 | 224 | 这种类型是任何可以通过[throw statement](11-statements.md#the-throw-statement)抛出的对象类型的基本接口。用户编写的类不能直接实现 `Throwable` 。 相反, 它必须扩展`Error` 或 `Exception`。 225 | 226 | 类型定义如下: 227 | 228 | ```PHP 229 | interface Throwable { 230 | function __toString(): string; 231 | function getCode(): int; 232 | function getFile(): string; 233 | function getLine(): int; 234 | function getMessage(): string; 235 | function getPrevious(): Throwable; 236 | function getTrace(): array; 237 | function getTraceAsString(): string; 238 | } 239 | ``` 240 | 接口成员定义如下: 241 | 242 | 243 | | Name | Purpose | 244 | | ------------------ | ------------------------------------------------------------ | 245 | | `__toString` | `string`; 以某种未指定的格式检索异常的字符串表示形式 | 246 | | `getCode` | `int`; 检索异常代码 | 247 | | `getFile` | `string`; 检索生成异常的脚本的名称 | 248 | | `getLine` | `int`; 检索生成异常的脚本中的源行号 | 249 | | `getMessage` | `string`; 检索异常消息 | 250 | | `getPrevious` | `Throwable`; 检索上一个异常(如果存在);否则返回`NULL` | 251 | | `getTrace` | `array`; 以数组形式检索函数堆栈 | 252 | | `getTraceAsString` | `string`; 检索以某种未指定格式格式化为单个字符串的函数堆栈跟踪信息 | 253 | 254 | ### 接口类 `Traversable` 255 | 256 | 此接口旨在作为所有可遍历类的基本接口。该接口定义如下: 257 | 258 | ```PHP 259 | interface Traversable 260 | { 261 | } 262 | ``` 263 | 264 | 这个接口没有成员。 265 | 266 | ### 接口类 `Serializable` 267 | 268 | 该接口支持自定义序列化。它的定义如下: 269 | 270 | ```PHP 271 | interface Serializable 272 | { 273 | function serialize(); 274 | function unserialize ($serialized); 275 | 276 | } 277 | ``` 278 | 279 | 接口成员定义如下: 280 | 281 | | Name | Purpose | 282 | | ------------- | ------------------------------------------------------------ | 283 | | `serialize` | 该实例方法返回当前实例的字符串表示形式。失败时,它返回 `NULL`。 | 284 | | `unserialize` | 这个实例方法从由`$serialized`指定的字符串形式构造一个对象。它不返回值。 | -------------------------------------------------------------------------------- /specifications/16-类扩展特性.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polarphp/langspecs/7bad1deb2306fb1f24e8f8a140c5a74bfd82e1b8/specifications/16-类扩展特性.md -------------------------------------------------------------------------------- /specifications/17-异常处理.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polarphp/langspecs/7bad1deb2306fb1f24e8f8a140c5a74bfd82e1b8/specifications/17-异常处理.md -------------------------------------------------------------------------------- /specifications/18-命名空间.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polarphp/langspecs/7bad1deb2306fb1f24e8f8a140c5a74bfd82e1b8/specifications/18-命名空间.md -------------------------------------------------------------------------------- /specifications/19-文法定义.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polarphp/langspecs/7bad1deb2306fb1f24e8f8a140c5a74bfd82e1b8/specifications/19-文法定义.md -------------------------------------------------------------------------------- /specifications/20-参考引用.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polarphp/langspecs/7bad1deb2306fb1f24e8f8a140c5a74bfd82e1b8/specifications/20-参考引用.md --------------------------------------------------------------------------------