亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

將現(xiàn)有程式碼庫(kù)更新到 php 8.1:處理具有 Null 值的不可空內(nèi)部函數(shù)參數(shù)
P粉344355715
P粉344355715 2023-10-31 20:01:48
0
2
1129

我剛開始升級(jí)我的程式碼以相容 php 8.1。我有很多程式碼片段,我將潛在的空值傳遞給內(nèi)部函數(shù)。

if (strlen($row) > 0) {
   ...
}

其中 $row 來(lái)自可能具有空值的來(lái)源(例如查詢)。這可能會(huì)產(chǎn)生棄用警告;在這種情況下:

已棄用:strlen():已棄用將 null 傳遞給字串類型的參數(shù) #1 ($string)

我正在尋找最簡(jiǎn)單、最省時(shí)的方法來(lái)處理升級(jí)此程式碼,例如修復(fù)可以進(jìn)行全域搜尋和替換的地方。似乎對(duì)我傳遞給內(nèi)部函數(shù)的變數(shù)進(jìn)行類型轉(zhuǎn)換,無(wú)需更改功能。

error_reporting(E_ALL);
$row = null;

if (strlen((string) $row) > 0) {
   ...
}

除了以這種方式編碼的道德方面之外,這種內(nèi)部功能方法是否存在問(wèn)題?有沒(méi)有更好的方法(除了完全重寫程式碼並以不同的方式處理空值之外)?我更喜歡這個(gè)向後相容 v7.4 的解決方案,儘管我可能會(huì)相容於 8.0。

我知道我的使用者定義函數(shù)還有其他選擇。

P粉344355715
P粉344355715

全部回覆(2)
P粉436410586

回答有關(guān)「處理升級(jí)此程式碼的最簡(jiǎn)單、最省時(shí)的方法」的問(wèn)題。

簡(jiǎn)而言之,你不能。


首先,一些背景...

大約15% 的開發(fā)者使用strict_types=1 ,所以您屬於大多數(shù)不這樣做的開發(fā)者中。

您現(xiàn)在可以忽略這個(gè)問(wèn)題(棄用),但是 PHP 9.0 會(huì)透過(guò)使其成為致命類型錯(cuò)誤而導(dǎo)致很多問(wèn)題。

也就是說(shuō),您仍然可以使用 NULL 連接字串:

$name = NULL;
$a = 'Hi ' . $name;

您仍然可以將 NULL 與空字串進(jìn)行比較:

if ('' == NULL) {
}

並且您仍然可以使用 NULL 進(jìn)行計(jì)算(它仍然被視為 0):

var_dump(3 + '5' + NULL); // Fine, int(8)
var_dump(NULL / 6); // Fine, int(0)

你仍然可以列印/回顯 NULL:

print(NULL);
echo NULL;

您仍然可以將 NULL 傳遞到 sprintf() 中,並使用 %s 將其強(qiáng)制為空字串,例如

sprintf('%s', NULL);

您仍然可以強(qiáng)制其他值(遵循規(guī)則),例如

strlen(15);
htmlspecialchars(1.2);
setcookie('c', false);

從那時(shí)起,NULL 強(qiáng)制就這樣運(yùn)作了,我假設(shè)從一開始,也有記錄:

  • To String:「null 總是轉(zhuǎn)換為空字串。」
  • 轉(zhuǎn)為整數(shù):「null 總是轉(zhuǎn)換為零(0)。」
  • 浮動(dòng):「對(duì)於其他類型的值,轉(zhuǎn)換的方式是先將值轉(zhuǎn)換為 int,然後再轉(zhuǎn)換為 float」
  • 轉(zhuǎn)為布林值:「轉(zhuǎn)換為布林值時(shí),以下值被視為 false [...] 特殊類型 NULL」

無(wú)論如何,要修復(fù)...第一部分,它會(huì)嘗試尋找您需要更新的程式碼。

只要可以將 NULL 傳遞給這些函數(shù)參數(shù)之一,就會(huì)發(fā)生這種情況。

至少有 335 受此影響的參數(shù)

還有一個(gè)額外的104,它們是有點(diǎn)可疑;和558 其中NULL 有問(wèn)題,你應(yīng)該在哪裡修復(fù)這些問(wèn)題,例如define(NULL, '值')。

Psalm 是我能找到的唯一能夠?qū)Υ颂峁椭墓ぞ摺?

詩(shī)篇需要處?kù)斗浅8叩臋z查等級(jí)(1、2 或 3)。

並且您不能使用基準(zhǔn)來(lái)忽略問(wèn)題(開發(fā)人員在現(xiàn)有專案中引入靜態(tài)分析的技術(shù),因此它只檢查新的/編輯過(guò)的程式碼)。

如果您之前沒(méi)有使用過(guò)靜態(tài)分析工具(不用擔(dān)心,建議僅使用33% 的開發(fā)者這樣做);然後預(yù)計(jì)會(huì)花費(fèi)大量時(shí)間修改程式碼(從第8 級(jí)開始,最寬鬆,然後慢慢提高)。

我無(wú)法使用PHPStan、Rector、PHP CodeSniffer、PHP CS Fixer 或PHPCompatibility 來(lái)查找這些問(wèn)題(來(lái)源)。


找到每個(gè)問(wèn)題後,第二部分就是編輯。

最不可能引起問(wèn)題的地方是更換水槽,例如

example_function(strval($name));
example_function((string) $name);
example_function($name ?? '');

或者,您可以嘗試追溯到變數(shù)的來(lái)源,並嘗試先封鎖將其設(shè)為 NULL。

以下是一些非常常見的 NULL 來(lái)源:

$search = (isset($_GET['q']) ? $_GET['q'] : NULL);
 
$search = ($_GET['q'] ?? NULL); // Fairly common (since PHP 7)
 
$search = filter_input(INPUT_GET, 'q');
 
$search = $request->input('q'); // Laravel
$search = $request->get('q'); // Symfony
$search = $this->request->getQuery('q'); // CakePHP
$search = $request->getGet('q'); // CodeIgniter
 
$value = mysqli_fetch_row($result);
$value = json_decode($json); // Invalid JSON, or nesting limit.
$value = array_pop($empty_array);

其中一些函數(shù)需要第二個(gè)參數(shù)來(lái)指定預(yù)設(shè)值,或者您可以提前使用strval()...但要小心,您的程式碼可能會(huì)通過(guò)($a = == NULL),而且您不想破壞它。

許多開發(fā)人員不會(huì)意識(shí)到他們的某些變數(shù)可以包含NULL - 例如期望

(他們創(chuàng)建的)始終提交所有輸入欄位;由於網(wǎng)路問(wèn)題、瀏覽器擴(kuò)充功能、用戶在瀏覽器中編輯DOM/URL 等,這種情況可能不會(huì)發(fā)生。


一年中的大部分時(shí)間我都在研究這個(gè)問(wèn)題。

我開始寫兩個(gè) RFC 來(lái)嘗試解決這個(gè)問(wèn)題。第一個(gè)是更新一些函數(shù)以接受NULL(這並不理想,因?yàn)樗屖褂胹trict_types 的開發(fā)人員感到不安); 第二個(gè)RFC 是允許NULL 在這種情況下繼續(xù)被強(qiáng)制. .....但我沒(méi)有不要將其付諸投票,因?yàn)槲覄倓偸盏搅舜罅控?fù)面反饋,並且我不希望將來(lái)引用該拒絕來(lái)解釋為什麼此問(wèn)題無(wú)法解決(而最初的更改幾乎沒(méi)有被討論,這一個(gè))。

似乎 NULL 的處理方式有所不同,因?yàn)樗鼜奈幢灰暈椤笜?biāo)量值」 - 我認(rèn)為許多開發(fā)人員並不關(guān)心這種區(qū)別,但它不時(shí)會(huì)出現(xiàn)。

與我合作過(guò)的開發(fā)人員中,大多數(shù)人都忽略了這個(gè)問(wèn)題(希望稍後能解決它,這可能不是最好的主意);例如

function ignore_null_coercion($errno, $errstr) {
  // https://github.com/php/php-src/blob/012ef7912a8a0bb7d11b2dc8d108cc859c51e8d7/Zend/zend_API.c#L458
  if ($errno === E_DEPRECATED && preg_match('/Passing null to parameter #.* of type .* is deprecated/', $errstr)) {
    return true;
  }
  return false;
}
set_error_handler('ignore_null_coercion', E_DEPRECATED);

有一個(gè)團(tuán)隊(duì)試圖將 strval() 套用到所有事情,例如修剪(strval($search))。但一年多後他們?nèi)匀话l(fā)現(xiàn)問(wèn)題(他們表示使用 8.1 alpha 1 進(jìn)行測(cè)試)。

我正在考慮的另一個(gè)選擇是創(chuàng)建一個(gè)庫(kù),在命名空間下將所有這些 ~335 個(gè)函數(shù)重新定義為可為空;例如

namespace allow_null_coercion;

function strlen(?string $string): int {
    return \strlen(\strval($string));
}

然後開發(fā)人員將包含該庫(kù),並自行使用命名空間:

namespace allow_null_coercion;

$search = $request->input('q'); // Could return NULL

// ...

echo strlen($search);
P粉087074897

如果您明確嘗試處理 null 的情況,那麼稍微乾淨(jìng)一點(diǎn)的修復(fù)方法是 strlen($row ?? '') 使用「null合併運(yùn)算子」。

在大多數(shù)情況下,兩者可能是等效的,但在strict_types=1 生效的情況下,如果值是可以轉(zhuǎn)換為字串的其他類型,則它們的行為會(huì)有所不同:

declare(strict_types=1);
$row = 42;
echo strlen($row); // TypeError: must be of type string, int given
echo strlen((string) $row); // Succeeds, outputting '2'
echo strlen($row ?? ''); // TypeError: must be of type string, int given

另一方面,請(qǐng)注意?? 運(yùn)算子是基於isset,而不是=== null,因此未定義變數(shù)的行為會(huì)有所不同:

declare(strict_types=1);
$row = [];
echo strlen($row['no_such_key']); // Warning: Undefined array key; TypeError: must be of type string, null given
echo strlen((string) $row['no_such_key']); // Warning: Undefined array key; outputs '0'
echo strlen($row['no_such_key'] ?? ''); // No warning, just outputs '0'

如果您關(guān)心這種情況,與舊行為最直接等效的程式碼會(huì)更加冗長(zhǎng):

echo strlen($row === null ? '' : $row);
最新下載
更多>
網(wǎng)站特效
網(wǎng)站源碼
網(wǎng)站素材
前端模板