1

我在功能测试中有以下断言:

// 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由于某种原因在 PHP 8.0 中返回了单数项。

我无法解释为什么会发生这种情况。回到 PHP 7.4,一切都再次过去了,所以它肯定与 PHP 版本相关联。故障排除很困难,因为当我启动时,无论我使用的是 PHP 7.4 还是 8.0,我总是得到“bar” artisan tinkerecho trans_choice("{0}foo|{1}bar|{2,}baz", 3);

语言环境不应该涉及到这个,因为我使用的是原始字符串,但是为了记录,localelocale_fallbackinconfig/app.php都设置为“en”。

4

1 回答 1

3

好的,经过大量之后dumpdd我能够追踪到不同的行为Illuminate\Translation\MessageSelector::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 中都不会通过。

于 2020-12-17T16:28:13.367 回答