您当前的位置:首页 > 指南 > 正文

php中函数定义的基本规范,PHP代码规范

关于【php中函数定义的基本规范】,今天犇涌小编给您分享一下,如果对您有所帮助别忘了关注本站哦。

内容导航:1、php中函数定义的基本规范:PHP代码规范2、php中函数定义的基本规范,PHP8函数和方法

1、php中函数定义的基本规范:PHP代码规范

PHP代码规范

代码风格规范

本规范希望通过制定一系列规范化PHP代码的规则,以减少在浏览不同作者的代码时,因代码风格的不同而造成不便。

当多名程序员在多个项目中合作时,就需要一个共同的编码规范, 而本文中的风格规范源自于多个不同项目代码风格的共同特性, 因此,本规范的价值在于我们都遵循这个编码风格,而不是在于它本身。

关键词 “必须”("MUST")、“一定不可/一定不能”("MUST NOT")、“需要”("REQUIRED")、 “将会”("SHALL")、“不会”("SHALL NOT")、“应该”("SHOULD")、“不该”("SHOULD NOT")、 “推荐”("RECOMMENDED")、“可以”("MAY")和”可选“("OPTIONAL")的详细描述可参见 RFC 2119 。

概览代码必须遵循 PSR-1 中的编码规范 。代码必须使用4个空格符而不是 tab键 进行缩进。每行的字符数应该软性保持在80个之内, 理论上一定不可多于120个, 但一定不能有硬性限制。每个namespace命名空间声明语句和use声明语句块后面,必须插入一个空白行。类的开始花括号({)必须写在其声明后自成一行,结束花括号(})也必须写在其主体后自成一行。方法的开始花括号({)必须写在函数声明后自成一行,结束花括号(})也必须写在函数主体后自成一行。类的属性和方法必须添加访问修饰符(privateprotected以及public),abstract以及final必须声明在访问修饰符之前,而static必须声明在访问修饰符之后。控制结构的关键字后必须要有一个空格符,而调用方法或函数时则一定不能有。控制结构的开始花括号({)必须写在声明的同一行,而结束花括号(})必须写在主体后自成一行。控制结构的开始左括号后和结束右括号前,都一定不能有空格符。

1.1. 例子

以下例子程序简单地展示了以上大部分规范:

<?phpnamespace Vendor\Package;use FooInterface;use BarClass as Bar;use OtherVendor\OtherPackage\BazClass;class Foo extends Bar implements FooInterface{ public function sampleFunction($a, $b = null) { if ($a === $b) { bar(); } elseif ($a > $b) { $foo->bar($arg1); } else { BazClass::bar($arg2, $arg3); } } final public static function bar() { // method body }}通则

2.1 基本编码准则

代码必须符合 PSR-1 中的所有规范。

2.2 文件

所有PHP文件必须使用Unix LF (linefeed)作为行的结束符。

所有PHP文件必须以一个空白行作为结束。

纯PHP代码文件必须省略最后的?>结束标签。

2.3. 行

行的长度一定不能有硬性的约束。

软性的长度约束一定要限制在120个字符以内,若超过此长度,带代码规范检查的编辑器一定要发出警告,不过一定不可发出错误提示。

每行不应该多于80个字符,大于80字符的行应该折成多行。

非空行后一定不能有多余的空格符。

空行可以使得阅读代码更加方便以及有助于代码的分块。

每行一定不能存在多于一条语句。

2.4. 缩进

代码必须使用4个空格符的缩进,一定不能用 tab键 。

备注: 使用空格而不是tab键缩进的好处在于, 避免在比较代码差异、打补丁、重阅代码以及注释时产生混淆。 并且,使用空格缩进,让对齐变得更方便。

2.5. 关键字 以及 True/False/Null

PHP所有 关键字必须全部小写。

常量truefalsenull也必须全部小写。

namespace 以及 use 声明

namespace 声明后 必须 插入一个空白行。

所有use 必须 在 namespace后声明。

每条use 声明语句 必须 只有一个 use关键词。

use 声明语句块后 必须 要有一个空白行。

例如:

<?phpnamespace Vendor\Package;use FooClass;use BarClass as Bar;use OtherVendor\OtherPackage\BazClass;// ... additional PHP code ...类、属性和方法

此处的“类”泛指所有的class类、接口以及traits可复用代码块。

4.1. 扩展与继承

关键词extendsimplements必须写在类名称的同一行。

类的开始花括号必须独占一行,结束花括号也必须在类主体后独占一行。

<?phpnamespace Vendor\Package;use FooClass;use BarClass as Bar;use OtherVendor\OtherPackage\BazClass;class ClassName extends ParentClass implements \ArrayAccess, \Countable{ // constants, properties, methods}

implements的继承列表也可以分成多行,这样的话,每个继承接口名称都必须分开独立成行,包括第一个。

<?phpnamespace Vendor\Package;use FooClass;use BarClass as Bar;use OtherVendor\OtherPackage\BazClass;class ClassName extends ParentClass implements \ArrayAccess, \Countable, \Serializable{ // constants, properties, methods}

4.2. 属性

每个属性都必须添加访问修饰符。

一定不可使用关键字var声明一个属性。

每条语句一定不可定义超过一个属性。

不要使用下划线作为前缀,来区分属性是 protected 或 private。

以下是属性声明的一个范例:

<?phpnamespace Vendor\Package;class ClassName{ public $foo = null;}

4.3. 方法

所有方法都必须添加访问修饰符。

不要使用下划线作为前缀,来区分方法是 protected 或 private。

方法名称后一定不能有空格符,其开始花括号必须独占一行,结束花括号也必须在方法主体后单独成一行。参数左括号后和右括号前一定不能有空格。

一个标准的方法声明可参照以下范例,留意其括号、逗号、空格以及花括号的位置。

<?phpnamespace Vendor\Package;class ClassName{ public function fooBarBaz($arg1, &$arg2, $arg3 = []) { // method body }}

4.4. 方法的参数

参数列表中,每个逗号后面必须要有一个空格,而逗号前面一定不能有空格。

有默认值的参数,必须放到参数列表的末尾。

<?phpnamespace Vendor\Package;class ClassName{ public function foo($arg1, &$arg2, $arg3 = []) { // method body }}

参数列表可以分列成多行,这样,包括第一个参数在内的每个参数都必须单独成行。

拆分成多行的参数列表后,结束括号以及方法开始花括号 必须 写在同一行,中间用一个空格分隔。

<?phpnamespace Vendor\Package;class ClassName{ public function aVeryLongMethodName( ClassTypeHint $arg1, &$arg2, array $arg3 = [] ) { // method body }}

4.5. abstract 、 final 、 以及 static

需要添加abstractfinal声明时,必须写在访问修饰符前,而static则必须写在其后。

<?phpnamespace Vendor\Package;abstract class ClassName{ protected static $foo; abstract protected function zim(); final public static function bar() { // method body }}4.6. 方法及函数调用

方法及函数调用时,方法名或函数名与参数左括号之间一定不能有空格,参数右括号前也一定不能有空格。每个逗号前一定不能有空格,但其后必须有一个空格。

<?phpbar();$foo->bar($arg1);Foo::bar($arg2, $arg3);

参数可以分列成多行,此时包括第一个参数在内的每个参数都必须单独成行。

<?php$foo->bar( $longArgument, $longerArgument, $muchLongerArgument);控制结构

控制结构的基本规范如下:

控制结构关键词后必须有一个空格。左括号(后一定不能有空格。右括号)前也一定不能有空格。右括号)与开始花括号{间一定有一个空格。结构体主体一定要有一次缩进。结束花括号}一定在结构体主体后单独成行。

每个结构体的主体都必须被包含在成对的花括号之中, 这能让结构体更加结构话,以及减少加入新行时,出错的可能性。

5.1. if 、 elseif 和 else

标准的if 结构如下代码所示,留意 括号、空格以及花括号的位置, 注意 elseelseif都与前面的结束花括号在同一行。

<?phpif ($expr1) { // if body} elseif ($expr2) { // elseif body} else { // else body;}

应该使用关键词elseif代替所有else if,以使得所有的控制关键字都像是单独的一个词。

5.2. switch 和 case

标准的switch结构如下代码所示,留意括号、空格以及花括号的位置。case语句必须相对switch进行一次缩进,而break语句以及case 内的其它语句都 必须 相对 case 进行一次缩进。 如果存在非空的 case直穿语句,主体里必须有类似// no break的注释。

<?phpswitch ($expr) { case 0: echo 'First case, with a break'; break; case 1: echo 'Second case, which falls through'; // no break case 2: case 3: case 4: echo 'Third case, return instead of break'; return; default: echo 'Default case'; break;}

5.3. while 和 do while

一个规范的while 语句应该如下所示,注意其 括号、空格以及花括号的位置。

<?phpwhile ($expr) { // structure body}

标准的do while 语句如下所示,同样的,注意其 括号、空格以及花括号的位置。

<?phpdo { // structure body;} while ($expr);

5.4. for

标准的for 语句如下所示,注意其 括号、空格以及花括号的位置。

<?phpfor ($i = 0; $i < 10; $i++) { // for body}

5.5. foreach

标准的foreach 语句如下所示,注意其 括号、空格以及花括号的位置。

<?phpforeach ($iterable as $key => $value) { // foreach body}

5.6. try, catch

标准的try catch 语句如下所示,注意其 括号、空格以及花括号的位置。

<?phptry { // try body} catch (FirstExceptionType $e) { // catch body} catch (OtherExceptionType $e) { // catch body}闭包

闭包声明时,关键词function后以及关键词use的前后都必须要有一个空格。

开始花括号必须写在声明的同一行,结束花括号必须紧跟主体结束的下一行。

参数列表和变量列表的左括号后以及右括号前,必须不能有空格。

参数和变量列表中,逗号前必须不能有空格,而逗号后必须要有空格。

闭包中有默认值的参数必须放到列表的后面。

标准的闭包声明语句如下所示,注意其 括号、逗号、空格以及花括号的位置。

<?php$closureWithArgs = function ($arg1, $arg2) { // body};$closureWithArgsAndVars = function ($arg1, $arg2) use ($var1, $var2) { // body};

参数列表以及变量列表可以分成多行,这样,包括第一个在内的每个参数或变量都必须单独成行,而列表的右括号与闭包的开始花括号必须放在同一行。

以下几个例子,包含了参数和变量列表被分成多行的多情况。

<?php$longArgs_noVars = function ( $longArgument, $longerArgument, $muchLongerArgument) { // body};$noArgs_longVars = function () use ( $longVar1, $longerVar2, $muchLongerVar3) { // body};$longArgs_longVars = function ( $longArgument, $longerArgument, $muchLongerArgument) use ( $longVar1, $longerVar2, $muchLongerVar3) { // body};$longArgs_shortVars = function ( $longArgument, $longerArgument, $muchLongerArgument) use ($var1) { // body};$shortArgs_longVars = function ($arg) use ( $longVar1, $longerVar2, $muchLongerVar3) { // body};

注意,闭包被直接用作函数或方法调用的参数时,以上规则仍然适用。

<?php$foo->bar( $arg1, function ($arg2) use ($var1) { // body }, $arg3);总结

以上规范难免有疏忽,其中包括但不仅限于:

全局变量和常量的定义函数的定义操作符和赋值行内对齐注释和文档描述块类名的前缀及后缀最佳实践

日志接口规范

本文制定了日志类库的通用接口规范。

本规范的主要目的,是为了让日志类库以简单通用的方式,通过接收一个Psr\Log\LoggerInterface 对象,来记录日志信息。 框架以及CMS内容管理系统如有需要,可以对此接口进行扩展,但需遵循本规范, 这才能保证在使用第三方的类库文件时,日志接口仍能正常对接。

本文中的实现者指的是实现了LoggerInterface接口的类库或者框架,反过来讲,他们就是LoggerInterface使用者

规范说明

1.1 基本规范

LoggerInterface 接口对外定义了八个方法,分别用来记录 RFC 5424 中定义的八个等级的日志:debug、 info、 notice、 warning、 error、 critical、 alert 以及 emergency 。第九个方法 —— log,其第一个参数为记录的等级。可使用一个预先定义的等级常量作为参数来调用此方法,必须与直接调用以上八个方法具有相同的效果。如果传入的等级常量参数没有预先定义,则必须抛出Psr\Log\InvalidArgumentException类型的异常。在不确定的情况下,使用者不该使用未支持的等级常量来调用此方法。

1.2 记录信息

以上每个方法都接受一个字符串类型或者是有__toString()方法的对象作为记录信息参数,这样,实现者就能把它当成字符串来处理,否则实现者必须自己把它转换成字符串。记录信息参数可以携带占位符,实现者可以根据上下文将其它替换成相应的值。

其中占位符必须与上下文数组中的键名保持一致。

占位符的名称必须由一个左花括号{以及一个右括号}包含。但花括号与名称之间一定不能有空格符。

占位符的名称应该只由A-Za-z,0-9、下划线_、以及英文的句号.组成,其它字符作为将来占位符规范的保留。

实现者可以通过对占位符采用不同的转义和转换策略,来生成最终的日志。 而使用者在不知道上下文的前提下,不该提前转义占位符。

以下是一个占位符使用的例子:

/** * 用上下文信息替换记录信息中的占位符 */function interpolate($message, array $context = array()){ // 构建一个花括号包含的键名的替换数组 $replace = array(); foreach ($context as $key => $val) { $replace['{' . $key . '}'] = $val; } // 替换记录信息中的占位符,最后返回修改后的记录信息。 return strtr($message, $replace);}// 含有带花括号占位符的记录信息。$message = "User {username} created";// 带有替换信息的上下文数组,键名为占位符名称,键值为替换值。$context = array('username' => 'bolivar');// 输出 "Username bolivar created"echo interpolate($message, $context);

1.3 上下文

每个记录函数都接受一个上下文数组参数,用来装载字符串类型无法表示的信息。它可以装载任何信息,所以实现者必须确保能正确处理其装载的信息,对于其装载的数据,一定不能抛出异常,或产生PHP出错、警告或提醒信息(error、warning、notice)。如需通过上下文参数传入了一个Exception对象,必须以'exception' 作为键名。 记录异常信息是很普遍的,所以如果它能够在记录类库的底层实现,就能够让实现者从异常信息中抽丝剥茧。 当然,实现者在使用它时,必须确保键名为'exception'的键值是否真的是一个Exception,毕竟它可以装载任何信息。

1.4 助手类和接口

Psr\Log\AbstractLogger类使得只需继承它和实现其中的log方法,就能够很轻易地实现LoggerInterface接口,而另外八个方法就能够把记录信息和上下文信息传给它。同样地,使用Psr\Log\LoggerTrait也只需实现其中的log方法。不过,需要特别注意的是,在traits可复用代码块还不能实现接口前,还需要implement LoggerInterface。在没有可用的日志记录器时,Psr\Log\NullLogger接口可以为使用者提供一个备用的日志“黑洞”。不过,当上下文的构建非常消耗资源时,带条件检查的日志记录或许是更好的办法。Psr\Log\LoggerAwareInterface接口仅包括一个setLogger(LoggerInterface $logger)方法,框架可以使用它实现自动连接任意的日志记录实例。Psr\Log\LoggerAwareTraittrait可复用代码块可以在任何的类里面使用,只需通过它提供的$this->logger,就可以轻松地实现等同的接口。Psr\Log\LogLevel类装载了八个记录等级常量。包

上述的接口、类和相关的异常类,以及一系列的实现检测文件,都包含在 psr/log 文件包中。

Psr\Log\LoggerInterface

<?phpnamespace Psr\Log;/** * 日志记录实例 * * 日志信息变量 —— message, **必须**是一个字符串或是实现了 __toString() 方法的对象。 * * 日志信息变量中**可以**包含格式如 “{foo}” (代表foo) 的占位符, * 它将会由上下文数组中键名为 "foo" 的键值替代。 * * 上下文数组可以携带任意的数据,唯一的限制是,当它携带的是一个 exception 对象时,它的键名 必须 是 "exception"。 * * 详情可参阅: https://github.com/PizzaLiu/PHP-FIG/blob/master/PSR-3-logger-interface-cn.md */interface LoggerInterface{ /** * 系统不可用 * * @param string $message * @param array $context * @return null */ public function emergency($message, array $context = array()); /** * **必须**立刻采取行动 * * 例如:在整个网站都垮掉了、数据库不可用了或者其他的情况下,**应该**发送一条警报短信把你叫醒。 * * @param string $message * @param array $context * @return null */ public function alert($message, array $context = array()); /** * 紧急情况 * * 例如:程序组件不可用或者出现非预期的异常。 * * @param string $message * @param array $context * @return null */ public function critical($message, array $context = array()); /** * 运行时出现的错误,不需要立刻采取行动,但必须记录下来以备检测。 * * @param string $message * @param array $context * @return null */ public function error($message, array $context = array()); /** * 出现非错误性的异常。 * * 例如:使用了被弃用的API、错误地使用了API或者非预想的不必要错误。 * * @param string $message * @param array $context * @return null */ public function warning($message, array $context = array()); /** * 一般性重要的事件。 * * @param string $message * @param array $context * @return null */ public function notice($message, array $context = array()); /** * 重要事件 * * 例如:用户登录和SQL记录。 * * @param string $message * @param array $context * @return null */ public function info($message, array $context = array()); /** * debug 详情 * * @param string $message * @param array $context * @return null */ public function debug($message, array $context = array()); /** * 任意等级的日志记录 * * @param mixed $level * @param string $message * @param array $context * @return null */ public function log($level, $message, array $context = array());}Psr\Log\LoggerAwareInterface

<?phpnamespace Psr\Log;/** * logger-aware 定义实例 */interface LoggerAwareInterface{ /** * 设置一个日志记录实例 * * @param LoggerInterface $logger * @return null */ public function setLogger(LoggerInterface $logger);}Psr\Log\LogLevel

<?phpnamespace Psr\Log;/** * 日志等级常量定义 */class LogLevel{ const EMERGENCY = 'emergency'; const ALERT = 'alert'; const CRITICAL = 'critical'; const ERROR = 'error'; const WARNING = 'warning'; const NOTICE = 'notice'; const INFO = 'info'; const DEBUG = 'debug';}

Autoloader

1. 概述

本 PSR 是关于由文件路径 自动载入 对应类的相关规范, 本规范是可互操作的,可以作为任一自动载入规范的补充,其中包括 PSR-0,此外, 本 PSR 还包括自动载入的类对应的文件存放路径规范。

2. 详细说明

此处的“类”泛指所有的class类、接口、traits可复用代码块以及其它类似结构。一个完整的类名需具有以下结构:

\<命名空间>(\<子命名空间>)*\<类名>完整的类名必须要有一个顶级命名空间,被称为 "vendor namespace";完整的类名可以有一个或多个子命名空间;完整的类名必须有一个最终的类名;完整的类名中任意一部分中的下划线都是没有特殊含义的;完整的类名可以由任意大小写字母组成;所有类名都必须是大小写敏感的。当根据完整的类名载入相应的文件……完整的类名中,去掉最前面的命名空间分隔符,前面连续的一个或多个命名空间和子命名空间,作为“命名空间前缀”,其必须与至少一个“文件基目录”相对应;紧接命名空间前缀后的子命名空间必须与相应的”文件基目录“相匹配,其中的命名空间分隔符将作为目录分隔符。末尾的类名必须与对应的以.php为后缀的文件同名。自动加载器(autoloader)的实现一定不能抛出异常、一定不能触发任一级别的错误信息以及不应该有返回值。

3. 例子

下表展示了符合规范完整类名、命名空间前缀和文件基目录所对应的文件路径。

无法复制加载中的内容

关于本规范的实现,可参阅 相关实例

注意:实例并不属于规范的一部分,且随时会有所变动。

参考:https://github.com/PizzaLiu/PHP-FIG

4. 代码规范工具

PHP Mess Detector(http://phpmd.org/)

PHP项目体检工具,根据你设定的标准(如单一文件代码体积,未使用的参数个数,未使用的方法数)检查PHP代码,超出设定的标准时报警。

PHP Copy Paste Detector(https://github.com/sebastianbergmann/...)

顾名思义,检查冗余代码的

PHP Dead Code Detector(https://github.com/sebastianbergmann/...)

看名字就知道了,检查从未被调用过的方法

PHP Code Sniffer(http://pear.php.net/package/PHP_CodeS...)

老牌代码格式化工具,PHP写的,Pear包,可自己hack,可集成到命令行里。

你还可以用jenkins把上述工具以plugins形式整合起来,做持续集成:http://jenkins-php.org/

你还可以用xinc+phing跟上述工具集成起来做持续集成后的自动化打包发布:http://code.google.com/p/xinc/

2、php中函数定义的基本规范,PHP8函数和方法

作者 | Deepak Vohra译者 | 刘雅梦,接下来我们就来聊聊关于php中函数定义的基本规范?以下内容大家不妨参考一二希望能帮到您!

php中函数定义的基本规范,PHP代码规范

php中函数定义的基本规范

作者 | Deepak Vohra

译者 | 刘雅梦

策划 | 丁晓昀

本文属于专题文章《深入浅出 PHP 8》。 根据w3tech的数据,PHP 仍然是 Web 上使用最广泛的脚本语言之一,77.3%的网站使用 PHP 进行服务器端编程。PHP 8 带来了许多新特性和其他改进,我们将在本系列文章中进行探讨。PHP 8.0 添加了对多个函数和方法相关特性的支持,其中一些是对现有特性的改进,而另一些则是全新的特性。PHP 8.1 中增强的可调用语法可用于通过可调用对象创建匿名函数。命名函数参数可以与位置参数一起使用,另外还有一个好处,即命名参数没有顺序,可以通过它们的名称来传达含义。纤程(Fiber)是可中断的函数,增加了对多任务的支持。

重新定义了私有方法上的继承

对象继承是大多数面向对象语言(包括 PHP)所使用的编程范式。它可以从任何扩展类中重写公共和受保护的方法,以及在类中定义的类属性和常量。在 PHP 中,公共方法不能通过更严格的访问来重新实现,例如将 public 方法设为 private 。为了演示这一点,考虑一个扩展了类 A 的类 B,它重新实现了类 A 中一个公共方法。

<?phpclass A{ public Function sortArray():string{ return "Class A method"; }} class B extends A{ private function sortArray():string{ return "Class B method"; }}$b=new B();echo $b->sortArray();

运行时,脚本会生成如下的一条错误信息:

致命错误:B::sortArray()的访问级别必须是公共的(与类A一样)公共方法不能重新实现。

相反,在类中定义的私有方法不是继承的,可以在扩展它的类中重新实现。例如,类 B 在下面的脚本中扩展了类 A,并重新实现了类 A 中一个私有方法。

<?phpclass A{ private function sortArray():string{ return "Class A method"; }} class B extends A{ private function sortArray(int $a):string{ return "Class B method"; }}

在 PHP 8.0 之前,对扩展类中私有方法的重新声明应用了两个限制:不允许更改 final 和 Static 修饰符。如果 private 方法被声明为 final ,则不允许扩展类重新声明该方法。如果私有方法被声明为静态的,那么它将在扩展类中保持静态。而且,如果私有方法没有static 修饰符,则不允许扩展类添加static 修饰符。在 PHP 8 中,这两个限制都被取消了。以下脚本在 PHP 8 中能正常运行。

<?phpclass A { private final static function sortArray():string{ return "Class A method"; }} class B extends A { private function sortArray(int $a):string{ return "Class B method"; }}

PHP 8 中唯一的私有方法限制是强制使用 private final 构造函数,当使用静态工厂方法作为替代时,有时会使用private final来禁用构造函数。

<?phpclass A { private final function __construct(){ }} class B extends A { private final function __construct(){ }}

该脚本生成如下的错误信息:

致命错误:不能重写最终方法A::__construct()

可变参数可以替换任意数量的函数参数

在 PHP 8 中,单个可变参数可以替换任意数量的函数参数。考虑下面的脚本,其中类 B 扩展了类 A,并用一个可变参数替换函数 sortArray 的三个参数。

<?phpclass A { public function sortArray(array $arrayToSort, string $sortType, int $arraySize) { if ($sortType == "asc") { sort($arrayToSort); foreach ($arrayToSort as $key => $val) { echo "$key = $val "; } } elseif ($sortType == "desc") { rsort($arrayToSort); foreach ($arrayToSort as $key => $val) { echo "$key = $val "; } } }}class B extends A { public function sortArray(...$multiple) { $arrayToSort= $multiple[0]; $sortType=$multiple[1]; if ($sortType == "asc") { sort($arrayToSort); foreach ($arrayTosort as $key => $val) { echo "$key = $val "; } } elseif ($sortType == "desc") { rsort($arrayToSort); foreach ($arrayToSort as $key => $val) { echo "$key = $val "; } } }}

可以使用多个参数调用类 B 中的 sortArray 函数。

$sortType="asc";$arrayToSort=array("B", "A", "f", "C");$arraySize=4; $b=new B();$b->sortArray($arrayToSort,$sortType,$arraySize)

输出结果如下所示:

0 = A 1 = B 2 = C 3 = f

简化了可调用语法

可调用(callable)是可以被调用的 PHP 表达式,例如实例方法、静态方法或可调用对象。例如,可调用可用于为方法调用创建简短的表达式。在 PHP 8.1 中,可以用新的可调用语法:

AVariableCallableExpression(...)

AVariableCallableExpression 表示一个变量可调用表达式。省略号…包含在语法中。

为什么要使用新的可调用语法呢?让我们通过一些示例来回顾一下传统的可调用语法是什么样子的:$f1 = 'strlen'(...);$f2 = [$someobj, 'somemethod'](...);$f3 = [SomeClass::class, 'somestaticmethod'](...);

这有两个问题:

语法涉及字符串和数组在创建可调用时,作用域不会被维护。为了演示这一点,请考虑如下用于对数组进行排序的脚本,其中 getSortArrayMethod() 方法返回 sortArray() 方法的可调用项,[$this,'sortArray'] 。

<?php class Sort { private array $arrayToSort; private string $sortType; public function __construct($arrayToSort,$sortType) { $this->arrayToSort = $arrayToSort; $this->sortType = $sortType; } public function getSortArrayMethod() { return [$this, 'sortArray']; } private function sortArray() { if ($this->sortType == "Asc") { sort($this->arrayToSort); foreach ($this->arrayToSort as $key => $val) { echo "$key = $val "; } } elseif ($this->sortType == "Desc") { rsort($this->arrayToSort); foreach ($this->arrayToSort as $key => $val) { echo "$key = $val "; } } else { shuffle($this->arrayToSort); foreach ($this->arrayToSort as $key => $val) { echo "$key = $val "; } } }}$sortType="Asc";$arrayToSort=array("B", "A", "f", "C");$sort = new Sort($arrayToSort,$sortType);$c = $sort->getSortArrayMethod();$c();

该脚本会生成如下的错误信息:

致命错误:未捕获错误:调用私有方法Sort::sortArray()来自全局作用域

使用 Closure::fromCallable([$this, 'sortArray']) 而不是 [$this, 'sortArray'] 可以解决作用域问题,但使用 Closure::fromCallable 方法会使调用变得冗长。新的可调用语法解决了作用域和语法冗长的问题。使用新的可调用语法,函数变为:

public function getSortArrayMethod() { return $this->sortArray(...); }

数组根据输出进行排序:

0 = A 1 = B 2 = C 3 = f

新语法可以与涉及字符串和数组的传统语法结合使用,以解决作用域问题。创建可调用的作用域将保持不变。

public function getSortArrayMethod() { return [$this, 'sortArray'](...); }

新的可调用语法也可以与静态方法一起使用,如下面的脚本所示,该脚本包含一个静态函数。

<?php class Sort { private array $arrayToSort; private string $sortType; public function __construct($arrayToSort,$sortType) { $this->arrayToSort = $arrayToSort; $this->sortType = $sortType; } public function getStaticMethod() { return Sort::aStaticFunction(...); } private static function aStaticFunction() { }}$sortType="Asc";$arrayToSort=array("B", "A", "f", "C");$sort = new Sort($arrayToSort,$sortType);$cStatic=$sort->getStaticMethod();$cStatic();

输出结果与之前的相同:

0 = A 1 = B 2 = C 3 =

以下是调用方法的等效方法:

return $this->sortArray(...); return Closure::fromCallable([$this, 'sortArray']);return [$this, 'sortArray'](...);

以下是调用静态方法的等效方法:

return Sort::aStaticFunction(...); return [Sort::class, 'aStaticFunction'](...); return Closure::fromCallable([Sort::class, 'aStaticFunction']);

即使函数声明了形参,也可以使用新的可调用语法。

<?php class Sort { private array $arrayToSort; private string $sortType; public function __construct($arrayToSort,$sortType) { $this->arrayToSort = $arrayToSort; $this->sortType = $sortType; } public function getSortArrayMethod() { return $this->sortArray(...); } private function sortArray(int $a,string $b) { if ($this->sortType == "Asc") { sort($this->arrayToSort); foreach ($this->arrayToSort as $key => $val) { echo "$key = $val "; } } elseif ($this->sortType == "Desc") { rsort($this->arrayToSort); foreach ($this->arrayToSort as $key => $val) { echo "$key = $val "; } } else { shuffle($this->arrayToSort); foreach ($this->arrayToSort as $key => $val) { echo "$key = $val "; } } }}

如果一个方法声明了任意参数,则必须使用它的参数来调用可调用对象。

$sortType="Asc";$arrayToSort=array("B", "A", "f", "C");$sort = new Sort($arrayToSort,$sortType);$c = $sort->getSortArrayMethod();$c(1,"A");

简化语法可用于任意的 PHP Callable 表达式

简化的可调用语法可以用于任意的 PHP 可调用表达式。用于对象创建的 new 运算符不支持可调用语法,因为可调用语法 AVariableCallableExpression(...) 没有指定构造函数参数的规定,这可能是必需的。以下是不支持的示例:

$sort = new Sort(...);

生成的错误信息为:

致命错误:不能为new表达式创建闭包

以下的脚本演示了受支持的所有可调用表达式。

<?php class Sort { private array $arrayToSort; private string $sortType; public function __construct($arrayToSort,$sortType) { $this->arrayToSort = $arrayToSort; $this->sortType = $sortType; } public function getSortArrayMethod() { return $this->sortArray(...); } public function getStaticMethod() { return Sort::aStaticFunction(...); } public static function aStaticFunction() { } public function sortArray(int $a,string $b) { if ($this->sortType == "Asc") { sort($this->arrayToSort); foreach ($this->arrayToSort as $key => $val) { echo "$key = $val "; } } elseif ($this->sortType == "Desc") { rsort($this->arrayToSort); foreach ($this->arrayToSort as $key => $val) { echo "$key = $val "; } } else { shuffle($this->arrayToSort); foreach ($this->arrayToSort as $key => $val) { echo "$key = $val "; } } } public function __invoke() {}}$sortType="Asc";$arrayToSort=array("B", "A", "f", "C"); $classStr = 'Sort';$staticmethodStr = 'aStaticFunction';$c1 = $classStr::$staticmethodStr(...);$methodStr = 'sortArray';$sort = new Sort($arrayToSort,$sortType);$c2 = strlen(...);$c3 = $sort(...); // 可调用对象$c4 = $sort->sortArray(...);$c5 = $sort->$methodStr(...);$c6 = Sort::aStaticFunction(...);$c7 = $classStr::$staticmethodStr(...);// 传统的可调用使用字符串,数组$c8 = 'strlen'(...);$c9 = [$sort, 'sortArray'](...);$c10 = [Sort::class, 'aStaticFunction'](...); $c11 = $sort->getSortArrayMethod();$c11(1,"A");$cStatic=$sort->getStaticMethod();$cStatic();

尾逗号和可选/必选的参数顺序

PHP 8.0 的另一个新特性是支持在函数的参数列表末尾添加一个尾逗号,以提高可读性。任何尾逗号都将被忽略。尾逗号可能并不总是有用的,但如果参数列表很长,或者参数名称很长,则可能会有用,因此可以垂直列出它们。闭包使用列表也支持尾逗号。

PHP 8.0 不支持在必选参数之前声明可选参数。在必选参数之前声明的可选参数都是隐式的必选参数。

下面的脚本演示了必选参数的隐式顺序,以及尾逗号的使用。

<?php function trailing_comma_example( $the_very_first_arg_of_this_function, $the_second_arg_of_this_function, $the_third_arg_of_this_function = 1, $the_fourth_arg_of_this_function, $the_last_arg_of_this_function,){ echo $the_third_arg_of_this_function; } trailing_comma_example(1,2,null,3,4) ?>

输出如下所示:

已弃用(不推荐):在必选参数$the_last_arg_of_this_function之前声明的可选参数$the_third_arg_of_tis_function将被隐式地视为必选参数

可空参数不会被视为可选参数,可以使用 $param=null 形式或显式可空类型在必选参数之前声明,脚本如下所示:

<?php class A {} function fn1(A $a = null, $b) {} function fn2(?A $a, $b) {} fn1(new A,1); fn2(null,1);?>

命名函数形参和实参

PHP 8.0 除了已经支持的位置形参和实参之外,还增加了对命名函数形参和实参的支持。命名参数在函数调用中的传递语法如下所示:

参数名称:参数值

命名参数的一些好处如下所示:

可以为函数参数指定一个有意义的名称,使它们能够自我记录按名称传递时,参数与顺序无关可以任意跳过默认值。在下面的脚本中, array_hashtable 函数声明了命名参数。 该函数传递的实参值可以带参数名,也可以不带参数名。当传递位置实参时,使用函数形参声明顺序。但传递命名实参时,可以使用任意顺序。

<?phpfunction array_hashtable($key1,$key2,$key3,$key4,$key5){ echo $key1.' '.$key2.' '.$key3.' '.$key4.' '.$key5; echo "<br>";}// 使用位置实参:array_hashtable(0, 10, 50, 20, 25);// 使用命名实参:array_hashtable(key2: 0, key5: 25, key1: 10, key4: 50, key3: 20);?>

输出结果为:

0 10 50 20 25

命名实参和位置实参可以在同一函数调用中使用。对相同的示例函数 array_hashtable 一起使用混合参数调用。

<?phpfunction array_hashtable($key1,$key2,$key3,$key4,$key5){ echo $key1.' '.$key2.' '.$key3.' '.$key4.' '.$key5; echo "<br>";}// 使用混合参数:array_hashtable(0, 10, 50, key5: 25, key4: 20); ?>

输出结果为:

0 10 50 20 25

请注意,命名参数只能用于位置参数之后。下面的脚本颠倒了顺序,在命名参数之后使用位置参数:

<?phpfunction array_hashtable($key1,$key2,$key3,$key4,$key5){ echo $key1.' '.$key2.' '.$key3.' '.$key4.' '.$key5; echo "<br>";}// Using mixed arguments:array_hashtable(0, 10, key3: 25, 50, key5: 20); ?>

该脚本生成的错误信息为:

致命错误:不能在命名参数后使用位置参数

即使使用命名参数,也不推荐在必选参数之前声明可选参数,脚本如下所示:

<?phpfunction array_hashtable($key1=0,$key2=10,$key3=20,$key4,$key5){ echo $key1.' '.$key2.' '.$key3.' '.$key4.' '.$key5; echo "<br>";}// 使用混合参数:array_hashtable(1,2,key3: 25, key4: 1,key5: 20); ?>

输出将包括已弃用(不推荐)信息:

已弃用(不推荐):在必选参数$key5之前声明的可选参数$key1被隐式视为必选参数已弃用(不推荐):在必选参数$key5之前声明的可选参数$key2被隐式视为必选参数已弃用(不推荐):在必选参数$key5之前声明的可选参数$key3被隐式视为必选参数

当在必选命名形参之后使用可选命名形参时,命名实参可用于跳过函数调用中的一个或多个可选形参,脚本如下所示:

<?phpfunction array_hashtable($key1,$key2,$key3=20,$key4=50,$key5=10){ echo $key1.' '.$key2.' '.$key3.' '.$key4.' '.$key5;echo "<br>";}// 使用混合参数:array_hashtable(key1:1, key2:2,key4: 25); ?>

输出结果为:

1 2 20 25 10

你可以只使用可选参数的子集来调用函数,而不用考虑它们的顺序。

<?phpfunction array_hashtable($key1=0,$key2=10,$key3=20,$key4=50,$key5=10){ echo $key1.' '.$key2.' '.$key3.' '.$key4.' '.$key5; echo "<br>";}// 使用混合参数:array_hashtable(1,2,key4: 25); ?>

输出结果如下所示:

1 2 20 25 10

即使使用可选参数的子集调用函数,也不能在命名参数之后使用位置参数,脚本如下所示:

<?phpfunction array_hashtable($key1=0,$key2=10,$key3=20,$key4=50,$key5=10){ echo $key1.' '.$key2.' '.$key3.' '.$key4.' '.$key5;echo "<br>";}// Using mixed arguments:array_hashtable(1,2,key4: 25,5); ?>

生成的错误信息以下所示:

致命错误:不能在命名参数后使用位置参数

PHP 8.1 改进了命名实参特性,在解包实参后支持命名实参,脚本如下所示:

<?phpfunction array_hashtable($key1,$key2,$key3=30,$key4=40,$key5=50){ echo $key1.' '.$key2.' '.$key3.' '.$key4.' '.$key5; echo "<br>";}echo array_hashtable(...[10, 20], key5: 40); echo array_hashtable(...['key2' => 2, 'key1' => 2], key4: 50); ?>

输出如下所示:

10 20 30 40 402 2 30 50 50

但是,命名的参数不能盖前面的参数,脚本如下所示:

<?phpfunction array_hashtable($key1,$key2,$key3=30,$key4=40,$key5=50){ echo $key1.' '.$key2.' '.$key3.' '.$key4.' '.$key5; echo "<br>";}echo array_hashtable(...[10, 20], key2: 40); ?>

输出如下所示:

致命错误:未捕获错误:命名参数$key2覆盖上一个参数。

非静态方法不能被静态调用

在 PHP 8.0 之前,如果在静态上下文中调用非静态方法,或者静态调用,则只会收到一条已弃用(不推荐)的信息。使用 8.0,你现在会收到一条错误信息。此外, $this 在静态上下文中是未定义的。为了演示这一点,请考虑如下的脚本,其中使用静态语法 A::aNonStaticMethod() 调用了非静态方法 aNonStaticMethod() 。

<?phpclass A{ function aNonStaticMethod() { }} A::aNonStaticMethod();

如果你运行这个脚本,将会得到如下的错误信息:

未捕获错误:非静态方法A::aNonStaticMethod()不能被静态调用

纤程

PHP 8.1 添加了对纤程(Fiber)多任务的支持。纤程是一个可中断的函数,它具有自己的堆栈。纤程可以从调用堆栈中的任何位置挂起,然后再恢复。新的 Fiber 类是一个 final 类,它支持以下的公共方法:

方法

描述

__construct(callable $callback) <br>

创建新Fiber实例的构造函数。 该参数是启动纤程时要调用的可调用对象。 提供给Fiber::start()的参数将作为给定可调用对象的参数提供。 可调用对象根本不需要调用Fiber::suspend(),或者即使调用也不需要直接调用。对Fiber::suspend()的调用可能在调用堆栈中嵌套很深。

start(mixed ...$args): mixed

启动纤程。该方法在纤程挂起或终止时返回。在构造纤程时,为所使用的可调用函数提供了可变的参数列表。如果纤程返回,则从第一个挂起点返回混合值或返回NULL。如果调用该方法时纤程已经启动,则会抛出FiberError错误。

resume(mixed $value = null): mixed

恢复纤程,从Fiber::suspend()返回给定的混合值。 当纤程挂起或终止时返回。 返回的混合值实际上是从下一个挂起点返回的,如果纤程返回,则返回NULL。 如果纤程尚未启动、正在运行或已终止,则抛出FiberError错误。

throw(Throwable $exception): mixed

将给定的异常从Fiber::suspend()抛出到纤程中。 当纤程挂起或终止时返回。 参数是Throwable $exception。 返回的混合值实际上是从下一个挂起点返回的,如果纤程返回,则返回NULL。 如果纤程尚未启动、正在运行或已终止,则抛出FiberError错误。

getReturn(): mixed

获取纤程回调的混合返回值。 如果纤程没有返回语句,则返回NULL。 如果纤程未终止或纤程抛出异常,则抛出FiberError错误。

isStarted(): bool

如果纤程已经启动,则返回布尔值True。

isSuspended(): bool

如果纤程已挂起,则返回布尔值True。

isRunning(): bool

如果纤程正在运行,则返回布尔值True。

isTerminated(): bool

如果纤程已终止,则返回布尔值True。

static suspend(mixed $value = null): mixed

挂起纤程。 返回对Fiber->start()、Fiber->resume() 或 Fiber->throw() 的调用执行。可以使用Fiber::resume()或Fiber::throw()恢复纤程。不能从纤程外的主线程调用。 参数是从Fiber::resume()或 Fiber::throw()返回的混合值$value。返回的混合值提供给Fiber::resume()。<br>如果不在纤程内(即,如果从主线程调用),则抛出FiberError错误。

static getCurrent(): ?Fiber

返回当前正在执行的纤程实例,如果在主线程中则返回NULL。

纤程只能启动一次,但可以挂起并恢复多次。下面的脚本通过使用纤程在数组上执行不同类型的排序来演示多任务处理。纤程在每次排序后都会挂起,然后再恢复执行不同类型的排序。

<?php $fiber = new Fiber(function (array $arr): void { sort($arr); foreach ($arr as $key => $val) { echo "$key = $val "; } echo "<br/>"; Fiber::suspend(); rsort($arr); foreach ($arr as $key => $val) { echo "$key = $val "; } echo "<br/>"; Fiber::suspend(); shuffle($arr); foreach ($arr as $key => $val) { echo "$key = $val "; } }); $arrayToSort=array("B", "A", "f", "C");$value = $fiber->start($arrayToSort); $fiber->resume();$fiber->resume(); ?>

输出如下所示:

0 = A 1 = B 2 = C 3 = f0 = f 1 = C 2 = B 3 = A0 = C 1 = f 2 = A 3 = B

如果纤程在第一次挂起后没有再恢复,则只进行一种类型的排序,这可以通过注释掉对 resume() 的两次调用来实现。

//$fiber->resume();//$fiber->resume();

输出的是第一次排序的结果:

0 = A 1 = B 2 = C 3 = f

Stringable 接口和 __toString()

PHP 8.0 引入了一个名为 Stringable 的新接口,它只提供一个方法 __toString() 。 __toString() 方法如果在类中提供,将隐式实现 Stringable 接口。考虑提供 __toString() 方法的类 A。

<?phpclass A { public function __toString(): string { return " "; }}echo (new A() instanceof Stringable);

该脚本从 Stringable 的类型检查中返回 1。

然而,反之则不然。如果类实现了 Stringable 接口,则必须显式提供 __toString() 方法,因为该方法不会自动添加,比如:

<?phpclass A implements Stringable {public function __toString(): string { } }

新的标准库函数

PHP 8 引入了许多属于其标准库的新函数。

str_contains 函数返回一个 bool 值,用于指示作为第一个参数的字符串是否包含作为第二个参数的字符串。以下脚本将返回 false :

<?phpif (str_contains('haystack', 'needle')) { echo true;} else { echo false;}

下面的脚本返回 1,或 true:

<?phpif (str_contains('haystack', 'hay')) { echo true;}else { echo "false";}

str_starts_with 函数返回一个bool 值 ,指示作为第一个参数的字符串是否以作为第二个参数的字符串开头。以下脚本将返回 false 。

<?phpif (str_contains('haystack', 'hay')) { echo true;}else { echo "false";}

下面的脚本将返回 1,或 true。

<?phpif (str_starts_with('haystack', 'needle')) { echo true;} else { echo false;}

str_ends_with 函数返回一个bool 值 ,指示作为第一个参数的字符串是否以作为第二个参数的字符串结尾。以下脚本将返回 false 。

<?phpif (str_starts_with('haystack', 'needle')) { echo true;} else { echo false;}

下面的脚本将返回 1,或 true。

<?phpif (str_starts_with('haystack', 'hay')) { echo true;} else { echo false;}

fdiv 函数将两个数字相除并返回一个 float 值,脚本如下所示:

<?phpvar_dump(fdiv(1.5, 1.3)); var_dump(fdiv(10, 2)); var_dump(fdiv(5.0, 0.0)); var_dump(fdiv(-2.0, 0.0)); var_dump(fdiv(0.0, 0.0)); var_dump(fdiv(5.0, 1.0)); var_dump(fdiv(10.0, 2));

输出为:

float(1.1538461538461537)float(5) float(INF) float(-INF)float(NAN)float(5)float(5)

fdatasync 函数在 Windows 上的别名为 fsync ,用于将数据同步到文件上的流中。为了演示它的用法,在包含要运行的 PHP 脚本的脚本目录中创建一个空文件 test.txt 。运行脚本:

<?php$file = 'test.txt';$stream = fopen($file, 'w');fwrite($stream, 'first line of data');fwrite($stream, "\r\n");fwrite($stream, 'second line of data');fwrite($stream, 'third line of data');fdatasync($stream);fclose($stream);

随后,打开 test.txt 文件会发现包含如下的文本:

first line of datasecond line of datathird line of data

array_is_list 函数返回布尔值,用于指示给定的数组是否为列表。数组必须从 0 开始,键必须是连续的整数,并且顺序正确。下面的脚本演示了 array_is_list 函数:

<?phpecho array_is_list([]); echo array_is_list(['1', 2, 3]); echo array_is_list([0 => 'a', 'b']); echo array_is_list([1 => 'a', 'b']); // falseecho array_is_list([1 => 'a', 0 => 'b']); // falseecho array_is_list([0 => 'a', 'b' => 'b']); // falseecho array_is_list([0 => 'a', 2 => 'b']); // false

输出为:

111

魔术方法必须要有正确的签名

魔术方法是 PHP 中用于覆盖默认操作的特殊方法。它们包括如下的方法,其中构造函数 __construct() 可能是大家最熟悉的:

__construct(),__destruct(), __call(),__callStatic(),__get(), __set(),__isset(),__unset(), __sleep(),__wakeup(),__serialize(),__unserialize(),__toString(),__invoke(),__set_state(),__clone(),__debugInfo()

从 PHP 8.0 开始,魔术方法定义的签名必须要是正确的,这意味着如果在方法参数或返回类型中使用类型声明,则它们必须与文档中的声明相同。新的 __toString() 方法的返回类型必须要声明为 string 。下面的演示将返回类型声明为 int :

<?phpclass A { public function __toString(): int { }}

将生成如下的错误信息:

致命错误:A::__toString():返回类型在声明时必须是字符串

但是,未通过定义声明返回类型的函数(如构造函数)不能声明返回类型,即使是 void 返回类型也不行。示例如下脚本所示:

<?phpclass A { public function __construct():void { }}

该脚本将返回如下的错误信息:

致命错误:方法A::__construct()不能声明返回类型

所有魔术方法,除了少数例外(例如 __construct() )外,都必须声明为具有公共可见性。为了演示这一点,声明了一个带有 private 可见性的 __callStatic 。

<?phpclass A { private static function __callStatic(string $name, array $arguments) {}}

输出的警告信息为:

警告:魔术方法A::__callStatic()必须要具有公共可见性

尽管可以省略混合返回类型,但方法签名也必须相同。例如,在下面的脚本中,类 A 声明了 __callStatic 而没有指定其返回类型,而类 B 将其第一个参数定义为int :

<?phpclass A { public static function __callStatic(string $name, array $arguments) {}class B { public static function __callStatic(int $name, array $arguments) {}}

输出的错误信息如下所示:

致命错误:B::__callStatic():参数 #1 ($name) 在声明时必须为字符串类型

返回类型与内部类的兼容性

在 PHP 8.1 中,大多数内部方法,即内部类中的方法,都已经“试探性地”开始声明返回类型。试探性地暗示,虽然在 8.1 中只会引发不推荐(Deprecation)通知,但在 9.0 版中,则会输出错误条件信息。因此,任何扩展类都必须声明与内部类相兼容的返回类型,否则将会引发已弃用(不推荐)通知。为了演示这一点,扩展内部类 Directory 并重新声明没有返回类型的函数 read() :

<?phpclass A extends Directory { public function read() { }}

该脚本将生成已弃用(不推荐)通知:

<?phpclass A extends Directory { public function read():string { return ""; }}

但是,以下脚本是可以的:

<?phpclass A extends Directory { public function read():string { return ""; }}

添加 #[\ReturnTypeWillChange] 属性能抑制已弃用(不推荐)通知:

<?phpclass A extends Directory { #[\ReturnTypeWillChange] public function read() { }}

\SensitiveParameter 属性

虽然包含有关方法参数的详细信息的异常堆栈跟踪对调试非常有用,但你可能不希望输出某些敏感参数的参数值,例如与密码和凭据关联的参数值。PHP 8.2 引入了一个名为 \SensitiveParameter 的新属性,这样,如果使用 \SensitivyParameter 属性注解方法的参数,则该参数的值不会在异常堆栈跟踪中输出。

为了演示这一点,考虑下面的脚本,其中函数 f1 具有与 \SensitiveParameter 属性关联的参数 $password 。

<?php function f1( $param1 = 1, #[\SensitiveParameter] $password = “s@5f_u7”, $param3 = null) { throw new \Exception('Error');}

为了演示 \SensitiveParameter 特性,该函数只是抛出一个异常。调用函数:

f1(param3: 'a');

请注意,异常堆栈跟踪不包含 $password 参数的值,而是列出了 Object(SensitiveParameterValue) 。

Stack trace: #0 : f1(1, Object(SensitiveParameterValue), 'a') #1 {main}

内置函数弃用/增强

内置函数 utf8_encode() 和 utf8_decode() 经常被误解,因为它们的名称意味着对任何字符串进行编码/解码。实际上,这些函数仅用于编码/解码 ISO8859-1,即“Latin-1”字符串。此外,它们生成的错误信息对于调试来说描述性不够。PHP 8.2 已经弃用了这些函数。下面的脚本使用了它们:

<?php $string_to_encode = "\x7A\x6A\xdB";$utf8_string = utf8_encode($string_to_encode);echo bin2hex($utf8_string), "\n";$utf8_string = "\x6A\x6B\xD3\xCB";$decoded_string = utf8_decode($utf8_string);echo bin2hex($decoded_string), "\n";

对于 PHP 8.2,会输出已弃用(不推荐)通知:

已弃用(不推荐):函数utf8_encode()已弃用已弃用(不推荐):函数utf8_decode()已弃用

在 PHP 8.2 中,函数 iterator_count 和 iterator_to_array 接受所有可迭代的对象。 iterator_to_array() 函数将迭代器的元素复制到数组中。 iterator_count() 函数对数组的元素进行计数。这些函数接受一个 $iterator 作为第一个参数。在 PHP 8.2 中,$iterator 参数的类型已从 Traversable 扩展为 Traversable|array ,以便接受任意的可迭代值。

下面的脚本演示了它们在 arrays 和 Traversables 中的使用。

<?php $a=array('1'=>'one', 'two', 'three', 'four');$iterator = new ArrayIterator($a);var_dump(iterator_to_array($iterator, true));var_dump(iterator_to_array($a, true));var_dump(iterator_count($iterator));var_dump(iterator_count($a));

输出如下所示:

array(4) { [1]=> string(3) "one" [2]=> string(3) "two" [3]=> string(5) "three" [4]=> string(4) "four" } array(4) { [1]=> string(3) "one" [2]=> string(3) "two" [3]=> string(5) "three" [4]=> string(4) "four" } int(4) int(4)

总结

在这篇 PHP 8 系列文章中,我们讨论了与函数和方法相关的新特性,其中最突出的是命名函数的形参/实参、简化的可调用语法和被称为纤程(Fiber)的可中断函数。

在本系列的下一篇文章中,我们将介绍 PHP 类型系统的新特性。

原文链接:

https://www.infoq.com/articles/php8-functions-methods/

相关阅读:

PHP 8:注解、match 表达式及其他改进

PHP 8:类和枚

本文关键词:php的函数定义格式,php中函数定义的基本规范有哪些,php如何定义一个函数?函数名区分大小写吗?,php定义方法,php中函数定义的基本规范是。这就是关于《php中函数定义的基本规范,PHP代码规范》的所有内容,希望对您能有所帮助!


声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,谢谢。

上一篇: 华为手机双卡 华为手机双卡双待怎么设置流量用哪个卡

下一篇: 会议议程安排英文版 会议议程安排怎样写



推荐阅读