Sage Pay / Opayo 表单集成 - PHP 8.1 - PHP 致命错误:未捕获错误:尝试在 null 上分配属性“start”

Sage Pay / Opayo form integration - PHP 8.1 - PHP Fatal error: Uncaught Error: Attempt to assign property "start" on null

提问人:Mike West 提问时间:5/3/2023 更新时间:5/3/2023 访问量:75

问:

我很感激有类似的问题,但我无法获得任何解决方案来使用我的(继承的)代码,因此非常感谢您提供的任何帮助。

我们通过表单集成使用 Sage Pay / Opayo 支付网关。 在完成/失败时,客户将被重定向到我们网站上带有加密_GET字符串的 URL。 解密后,调用 getToken 函数 ( ) 从数组中获取值。$values = getToken($Decoded);

但是,并非所有令牌都始终填充,我怀疑这些 null 值可能是问题的根源。

该代码在 PHP 7.1 上运行良好,但 PHP 8.1 抛出:

[03-五月-2023 15:12:15 欧洲/伦敦]PHP 致命错误:未捕获错误:尝试在 /home/sitename/public_html/ch_functions.php:166 中的 null 上分配属性“start” 堆栈跟踪: #0 /home/sitename/public_html/not_completed.php(32):getToken('VendorTxCode=AP...') #1 {主要} 在第 166 行的 /home/sitename/public_html/ch_functions.php 中抛出

代码是,失败的是:$resultArray[$i]->start = $start;

function getToken($thisString) {

    // List the possible tokens
    $Tokens = array("Status","StatusDetail","VendorTxCode","VPSTxId","TxAuthNo","Amount","AVSCV2","AddressResult","PostCodeResult","CV2Result","GiftAid","3DSecureStatus","CAVV", "AddressStatus", "PayerStatus", "CardType", "Last4Digits","BankAuthCode","DeclineCode");

    // Initialise arrays
    $output = array();
    $resultArray = array();
    
    // Get the next token in the sequence
    for ($i = count($Tokens)-1; $i >= 0 ; $i--){
        // Find the position in the string
        $start = strpos($thisString, $Tokens[$i]);
        // If it's present
        if ($start !== false){
            // Record position and token name
            $resultArray[$i]->start = $start;
            $resultArray[$i]->token = $Tokens[$i];
        }
    }
    
    // Sort in order of position
    sort($resultArray);

    // Go through the result array, getting the token values
    for ($i = 0; $i<count($resultArray); $i++){
        // Get the start point of the value
        $valueStart = $resultArray[$i]->start + strlen($resultArray[$i]->token) + 1;
        // Get the length of the value
        if ($i==(count($resultArray)-1)) {
            $output[$resultArray[$i]->token] = substr($thisString, $valueStart);
        } else {
            $valueLength = $resultArray[$i+1]->start - $resultArray[$i]->start - strlen($resultArray[$i]->token) - 2;
            $output[$resultArray[$i]->token] = substr($thisString, $valueStart, $valueLength);
        }           

    }

    // Return the ouput array
    return $output;

}
php-8.1

评论

1赞 Alex Howansky 5/3/2023
你假设这是一个对象,但事实并非如此。用于查看该数组中的实际内容。$resultArray[$i]var_dump()
0赞 Mike West 5/3/2023
@AlexHowansky - 在代码的哪个点?填充数组时不会失败吗?
0赞 aynber 5/3/2023
$resultArray是一个数组,在创建它之前不存在于循环中。您正在对尚未创建的内容使用对象访问器。将数组键初始化为循环顶部的对象,或使用数组访问器。$result[$i]
0赞 Mike West 5/3/2023
啊哈!谢谢!''' $resultArray[$i] = (对象)[];$resultArray[$i]->开始 = $start;$resultArray[$i]->token = $Tokens[$i];'''似乎工作正常

答:

0赞 Alex Howansky 5/3/2023 #1

您作为对象进行引用,但数组为空,因此没有要引用的对象。在 PHP 7.4 及更早版本中,您可以这样做:$resultArray[$i]

$x = [];
$x[0]->foo = 1;

PHP 会动态创建一个对象,然后动态创建 foo 属性,但会发出警告:stdClass$x[0]

警告:从...在线。。。

您当前正在禁止显示或忽略此警告。在 PHP 8.0 中,这会生成一个致命错误。因此,在尝试设置其值之前,只需创建一个空对象:

if ($start !== false) {
    $resultArray[$i] = new stdClass();
    $resultArray[$i]->start = $start;
    $resultArray[$i]->token = $Tokens[$i];
}

艺术

if ($start !== false) {
    $resultArray[$i] = (object) [
        'start' => $start,
        'token' => $Tokens[$i],
    ];
}

评论

0赞 Mike West 5/3/2023
其中一个比另一个好吗?
0赞 Alex Howansky 5/3/2023
嗯,这是非常主观的,但我认为后者更具可读性。