您好,登錄后才能下訂單哦!
這篇“PHP8.2有哪些新特性”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“PHP8.2有哪些新特性”文章吧。
null和false將作為獨立的類型
PHP并不會陷入到完美的類型安全方向中,但是從技術的角度考慮,將null和false作為獨立的數據類型是值得的。一般情況下,PHP的很多常見的函數,會通過返回false表示出錯了。比如在file_get_content中:
file_get_contents(/* … */): string|false
在以前,false可以在聯合類型中使用,但是不能獨立使用,在PHP8.2中可以單獨使用:
function alwaysFalse(): false { return false; }
當然,對于這個做法,一些開發者都持謹慎態度。他并不支持true作為獨立類型。這些開發者們認為,false只是一個值,類型應該代表類別而不是一個值。當然在類型系統中,有一個概念是單元類型,它是只允許一個值的類型。但是這真的有用嗎?
不過另一個RFC也正在討論將true作為一種類型添加到PHP中。
一個獨立的null卻很有意義,這樣可以簡單地實現空對象模式:
class Post { public function getAuthor(): ?string { /* … */ } } class NullPost extends Post { public function getAuthor(): null { /* … */ } }
這對NullPost::getAuthor()能夠說它只會返回null,不必像以前那樣必須將null和string一起聯合聲明。
棄用動態屬性
對于語言規范來說,這是更好的設計,但是也會限制很多用法。動態屬性在PHP8.2中被棄用,并且會在PHP中拋出錯誤異常。
什么是動態屬性?就是你沒有在類中聲明這些屬性,但是仍然可以設置和獲取:
class Post { public string $title; } // … $post->name = 'Name'; // 在PHP8.2中不能這樣使用,因為并沒有在類中聲明
不過放心,__set和__get等魔術方法將仍然按預期中工作:
class Post { private array $properties = []; public function __set(string $name, mixed $value): void { $this->properties[$name] = $value; } } // … $post->name = 'Name';
標準對象也是如此:stdClass將繼續支持動態屬性。
PHP曾經是一種動態程度很強的動態語言,但是現在已經有很多人愿意接受更加嚴格的編程方式了。盡可能的嚴格,盡可能的依賴靜態分析是一件好事,這能讓開發者們寫出更好的代碼。
不過可能一部分很看重動態屬性的開發人員對這種變化會很不滿意,如果你不想在使用PHP8.2時看到這些警告,可以這樣做:
可以使用#[AllowDynamicProperties]
#[AllowDynamicProperties] class Post { public string $title; } // … $post->name = 'Name'; // 一切正常
另一種方法是修改報警級別,但不建議這樣做。等你打算升級到PHP9.0時會遇到麻煩。
error_reporting(E_ALL ^ E_DEPRECATED);
追蹤調用時參數脫敏
什么叫參數脫敏?在我們開發時,遇到錯誤,都會使用Trace調試,但是目前的堆棧記錄下一些敏感數據,比如環境變量、密碼、用戶。
在PHP8.2中允許對參數進行一些編訂( Redact ,姑且叫做編訂,有一些修飾的意思,但直接稱為修飾并不合適),比如將一些參數設置脫敏,這樣這些參數的調用值不會在堆棧信息中列出:
function test( $foo, #[\SensitiveParameter] $bar, $baz ) { throw new Exception('Error'); } test('foo', 'bar', 'baz');
如果報錯的話,會發現,第二個參數bar并沒有記錄實際的值。這樣能起到脫敏的作用,如果傳的是密碼的話,就不會別記錄下來。
Fatal error: Uncaught Exception: Error in test.php:8 Stack trace: #0 test.php(11): test('foo', Object(SensitiveParameterValue), 'baz') #1 {main} thrown in test.php on line 8
棄用了部分對象的調用方式
一些以前的調用對象方式杯棄用了。這里面一些是需要通過call_user_func($callable)來調用的,而不是能夠$callable()直接調用的。
"self::method" "parent::method" "static::method" ["self", "method"] ["parent", "method"] ["static", "method"] ["Foo", "Bar::method"] [new Foo, "Bar::method"]
為什么要這樣做呢?Nikita在RFC討論中很好的做出了解釋:
這些廢棄的調用都是有關上下文的, “self::method”所指的方法取決于從哪個類執行調用或可調用性檢查。實際上,當以[new Foo, "parent::method"]的形式使用時,這通常也適用于最后兩種情況。
減少可調用對象的上下文相關性是本RFC的次要目標。在這個RFC之后,唯一剩下的范圍依賴是方法可見性:“Foo::bar”可能在一個范圍內可見,但在另一個范圍內不可見。如果將來可調用對象僅限于公共方法,那么可調用類型將變得明確定義并且可以用作屬性類型。但是,對可見性處理的更改不建議作為本RFC的一部分。
提升對未定義變量的檢測機制和級別
未定義的變量是那些在被讀取之前還沒有被初始化的變量。訪問未定義的變量當前會發出E_WARNING“警告:未定義的變量$varname”,并將變量視為null,但不會中斷執行,從而允許代碼執行繼續有增無減,但可能處于意外狀態。
目前可以通過一些配置,讓PHP執行時對未定義變量產生錯誤級異常,但這需要單獨配置。PHP應當默認提供更安全的檢驗。
一般什么情況下會出現未定義變量的情況呢?
用法1
變量在某個分支中聲明,比如在if中設置一個值。
if ( $user -> admin ) { $restricted = false ; } if ( $restricted ) { die ( '你沒有進入這里的權限' ) ; }
用法2
變量拼寫錯誤:
$name = 'Joe'; echo 'Welcome, ' . $naame;
這種用法在1中也可能會發生:
if ($user->admin) { $restricted = false; } else { $restrictedd = true; } if ($restricted) { die('You do not have permission to be here'); }
用法3
在循環中定義,但這個循環可能并沒有執行:
while ($item = $itr->next()) { $counter++; // 定義變量 } // 這里調用了變量,但是很有可能并沒有定義這個變量 echo 'You scanned ' . $counter . ' items';
解決方法
在這些分支之前提前定義好一個默認值。
對于第1種用法:
$restricted = true; if ($user->admin) { $restricted = false; } if ($restricted) { die('You do not have permission to be here'); }
對于第3種用法:
$counter = 0; while ($item = $itr->next()) { $counter++; } echo 'You scanned ' . $counter . ' items';
這樣做的好處是消除了整個訪問和使用這些未定義變量的后果,以及回退到引擎默認狀態的用戶態錯誤。這樣我們提供了另一層保護,防止PHP程序發生了這種意外后繼續運行。
這種更改也會讓PHP引擎和JIT等方面不會那么復雜。
這個版本主要是針對PHP9.0的,在PHP8.2的還是警告,在以后會將這種行為提升到錯誤級別。
增加只讀類
通過給類添加只讀修飾符來聲明只讀類。
readonly class Test { public string $prop; }
這樣做會隱式地將類的所有實例屬性標記為只讀。此外,它將阻止創建動態屬性。
readonly class Foo { public int $bar; public function __construct() { $this->bar = 1; } } $foo = new Foo(); $foo->bar = 2; // 拋出錯誤,不能修改只讀屬性 Foo::$bar $foo->baz = 1; // 拋出錯誤:不能動態創建屬性 Foo::$baz
可以通過增加#[AllowDynamicProperties]屬性,可以不觸發錯誤的情況下創建動態屬性。
#[AllowDynamicProperties] readonly class Foo { }
一些限制:
由于是只讀類,必須對屬性聲明類型:
readonly class Foo { public $bar; } // 以上定義會產生錯誤。
不能使用靜態屬性:
readonly class Foo { public static int $bar; } // 拋出錯誤: 只讀屬性不能聲明靜態類型
以上就是關于“PHP8.2有哪些新特性”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。