我在功能测试中有以下断言:
// just a convenience method to post a CSV file
$this->importData($postdata, $csv)
->assertStatus(200)
->assertExactJson([
"alert" => null,
// response text copied from RoomController::import()
"message" => sprintf(__("%d items were created or updated."), count($csv_data)),
]);
这在PHP 7.4中没有问题。在没有对我的应用程序代码进行任何更改的情况下,我更新到了PHP 8.0,现在呈现的是:
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'{"alert":null,"message":"2 items were created or updated."}'
+'{"alert":null,"message":"2 item was created or updated."}'
有问题的控制器代码如下所示:
if ($errcount === 0) {
$response_code = 200;
$msg = sprintf(
trans_choice(
"{0}No items were created or updated.|{1}%d item was created or updated.|{2,}%d items were created or updated.",
$count
),
$count
);
} else {
// some other stuff
}
return response()->json(["message" => $msg, "alert" => $alert], $response_code);
所以我的问题是trans_choice
由于某种原因在PHP8.0中返回了单数项。
我无法解释为什么会发生这种情况。回到PHP 7.4,一切都会再次通过,所以它肯定与PHP版本有关。故障排除是困难的,因为当我启动CCD_ 2并执行CCD_;条";因此,无论我使用的是PHP 7.4还是8.0。
Locale不应该涉及到这一点,因为我使用的是原始字符串,但对于记录,config/app.php
中的locale
和locale_fallback
都设置为"0";en";。
好吧,经过大量的dump
和dd
,我能够将不同的行为追溯到IlluminateTranslationMessageSelector::extractFromString()
,同时也意识到我使用了错误的语法。
该方法是执行一些正则表达式,然后在条件和值之间进行松散的比较。它在PHP 7.4中起作用的唯一原因是;2;大致等于2。8.0中以更合理的方式将字符串与整数进行比较,因此该方法在所有情况下都返回null,并使用单数默认值。
但是,我不应该使用正则表达式语法{2,}
,而是应该这样定义我的字符串:
"{0}No items were created or updated.|{1}%d item was created or updated.|{2,*}%d items were created or updated."
星号由函数检测到,并使回路短路以给出正确的值。如果我测试的是0、1或2以外的任何值,那么我的测试在任何版本的PHP中都不会通过。