如果方法名稱設定為空字串,則會影響類別本身的旗標,而不是個別方法的旗標。這可以用於移除類別的「final」屬性。
<?php
declare(strict_types=1);
final class MyClass { function mymethod() {} };
uopz_flags(MyClass::class, '', 0);
?>
注意:雖然沒有記錄,但將方法設定為 NULL 也會以類別旗標為目標,但是,由於開發人員不正確的函式簽章,該語法會與嚴格類型衝突。
(PECL uopz 2 >= 2.0.2, PECL uopz 5, PECL uopz 6, PECL uopz 7)
uopz_flags — 取得或設定函式或類別的旗標
在執行時期取得或設定類別或函式項目的旗標
class
類別名稱
function
函式名稱。如果給定了 class
參數,且 function
參數傳入空字串,uopz_flags() 將會取得或設定類別項目的旗標。
flags
一組有效的 ZEND_ACC_ 旗標。如果省略,uopz_flags() 將作為 getter 使用。
如果設定旗標,則返回舊的旗標;否則返回目前的旗標
從 PHP 7.4.0 開始,如果傳入了 flags
參數,且 OPcache 已啟用,並且 class
的類別項目或 function
的函式項目是不可變的,uopz_flags() 將會拋出 RuntimeException。
版本 | 說明 |
---|---|
PECL uopz 5.0.0 | flags 參數現在是可選的。以前,必須傳入 ZEND_ACC_FETCH 才能將 uopz_flags() 作為 getter 使用。 |
範例 #1 uopz_flags() 範例
<?php
class Test {
public function method() {
return __CLASS__;
}
}
$flags = uopz_flags("Test", "method");
var_dump((bool) (uopz_flags("Test", "method") & ZEND_ACC_PRIVATE));
var_dump((bool) (uopz_flags("Test", "method") & ZEND_ACC_STATIC));
var_dump(uopz_flags("Test", "method", $flags|ZEND_ACC_STATIC|ZEND_ACC_PRIVATE));
var_dump((bool) (uopz_flags("Test", "method") & ZEND_ACC_PRIVATE));
var_dump((bool) (uopz_flags("Test", "method") & ZEND_ACC_STATIC));
?>
上述範例將輸出:
bool(false) bool(false) int(1234567890) bool(true) bool(true)
範例 #2 「取消完成」一個類別
<?php
final class MyClass
{
}
$flags = uopz_flags(MyClass::class, '');
uopz_flags(MyClass::class, '', $flags & ~ZEND_ACC_FINAL);
var_dump((new ReflectionClass(MyClass::class))->isFinal());
?>
上述範例將輸出:
bool(false)
如果方法名稱設定為空字串,則會影響類別本身的旗標,而不是個別方法的旗標。這可以用於移除類別的「final」屬性。
<?php
declare(strict_types=1);
final class MyClass { function mymethod() {} };
uopz_flags(MyClass::class, '', 0);
?>
注意:雖然沒有記錄,但將方法設定為 NULL 也會以類別旗標為目標,但是,由於開發人員不正確的函式簽章,該語法會與嚴格類型衝突。
澄清上述提示
「... 類別的類別項目或函式的函式項目是不可變的」
PHP 類別或函式定義都沒有任何「不可變」關鍵字 - 因此這個註釋令人困惑,因為它暗示 PHP 程式設計師可以控制這一點。實際上,提到的「不可變」狀態是 OPcache 的內部控制最佳化/共享記憶體功能。
因此,如果需要透過「uopz_flags()」設定(更改)PHP 類別或函式的旗標,則需要使用「opcache.blacklist_filename」INI 參數將參考類別或函式的 PHP 指令碼從 OPcache 中排除。