<bdo id="q0ghy"><meter id="q0ghy"></meter></bdo>
    <rt id="q0ghy"></rt>
  1. <label id="q0ghy"></label>
    <bdo id="q0ghy"><meter id="q0ghy"></meter></bdo>
    當前位置:首頁 > 生活小常識 > 正文
    已解決

    php中函數定義的基本規范,PHP代碼規范

    來自網友在路上 11468146提問 提問時間:2023-08-02 19:39:43閱讀次數: 146

    最佳答案 問答題庫1468位專家為你答疑解惑

    關于【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代碼規范》的所有內容,希望對您能有所幫助!更多的知識請繼續關注《犇涌向乾》百科知識網站:!

    99%的人還看了

    猜你感興趣

    版權申明

    本文" php中函數定義的基本規范,PHP代碼規范":http://eshow365.cn/3-3689-0.html 內容來自互聯網,請自行判斷內容的正確性。如有侵權請聯系我們,立即刪除!

    主站蜘蛛池模板: 中文字幕亚洲综合小综合在线 | 久久综合国产乱子伦精品免费 | 伊人色综合久久大香| 亚洲精品综合久久| 久久综合久久久久| 久久久久高潮综合影院| 国产成人综合久久精品免费| 综合久久国产九一剧情麻豆| 涩涩色中文综合亚洲| 国产成人精品综合久久久| 亚洲乱码中文字幕小综合 | 狠狠88综合久久久久综合网| 国产91色综合久久免费| 在线亚洲97se亚洲综合在线 | 亚洲国产天堂久久综合网站| 色天天综合久久久久综合片| 无码专区久久综合久中文字幕| 狠狠色噜噜狠狠狠狠色吗综合| 久久综合综合久久97色| segui久久综合精品| 久久婷婷五月综合色精品| 激情综合亚洲色婷婷五月APP| 久久精品综合一区二区三区| 亚洲 综合 国产 欧洲 丝袜| 亚洲人成网站999久久久综合| 综合自拍亚洲综合图不卡区| 色诱久久久久综合网ywww| 国产成人亚洲综合| 国产天堂一区二区综合| 一本大道AV伊人久久综合| 国产成人精品综合| 国产成人久久综合二区| 色噜噜狠狠色综合久| 五月天激情综合网丁香婷婷| 一本大道无香蕉综合在线| 区三区激情福利综合中文字幕在线一区| 国产精品免费综合一区视频| 国产成人综合久久久久久| 伊人久久大香线蕉综合Av | 色视频综合无码一区二区三区| 天天做天天爱天天爽综合区|