将 API 函数参数键入提示或转换为 int 的最佳方法是什么?

What is the best way to type-hint or cast a API function parameter into int?

提问人:irohit786 提问时间:8/29/2022 最后编辑:Marcin Orlowskiirohit786 更新时间:8/29/2022 访问量:87

问:

我正在使用 Drupal 9 并使用 OAuth 来验证我的 DELETE API 请求。我有一个函数,可以响应 DELETE 请求,并将 student_no 作为删除请求 URL 中的参数。例如,当发送删除请求 https://www.myapplicationurl.com/999999 时,我的函数将999999作为student_no接收。我的功能如下:

public function delete( $student_no) {
  $node_array = \Drupal::entityTypeManager()->getStorage('node')->loadByProperties(['student_no' => $student_no]);
  $node = reset($node_array);

  if ($node && ($node->bundle() == 'student')) {
    try {
      $node->delete();
      $response_code = 200;
      $response = ["code" => $response_code, "message" => 'deleted', "student_no" => $student_no];

       return new JsonResponse($response, $response_code, $headers);
    } catch (ClientException | RequestException | TransferException | BadResponseException $exception) {
      \Drupal::service('myapi.log_service')->api_log("Stiudent Delete API Exception: {$exception}");
      $response_code = 405;
      $message = json_decode((string) (($exception->getResponse()) ? $exception->getResponse()->getBody() : ''));
      $response = ["code" => $response_code, "message" => 'deleted', "student_no" => $student_no];

      return new JsonResponse($response, $response_code, $headers);
    }
  } else {
    $response_code = 404;
    $response = ["code" => $response_code, "message" => "Student does not exist", "student_no" => $student_no];

    return new JsonResponse($response, $response_code, $headers);
  }
} 

现在,一切都按预期工作,但问题出在我的回复中,$student_no 以字符串形式出现,如“999999”。数组$response var_dump是:如何确保student_id始终是数字?我想我可以做两件事:array(3) { ["code"]=> int(200) ["message"]=> string(7) "deleted" ["student_no"]=> string(6) "999999" }

  1. 我可以将学生编号转换为整数作为函数中的第一步,例如,但这会将正确的字符串转换为 0,例如,如果传递了 https://www.myapplicationurl.com/somerandomstring,则在转换后将有效地将 $student_no 设置为 0。我不确定这样做是否正确。$student_no = (int) $student_no;

  2. 我可以将 hint student_no 键入为整数,这似乎很完美,但是如果像上面的 #1 那样在 url 中传递字符串,它会给出 500,内部服务器错误,这是一个很大的禁忌,因为它会违反我的 API 合同,它只允许我返回 200、404 或 405 作为错误代码。对于我来说,要实现这一点,我需要捕获 500 异常,我不确定该怎么做,否则,我必须放弃这种方法。public function delete(int $student_no)

请提出最佳的前进方向。谢谢。

PHP REST 强制转换 类型提示

评论

1赞 Rain 8/29/2022
如果你的函数只期望student_no,那么你为什么要关心“somerandomstring”返回 0?如果student_no是 0,那么就拒绝它,因为没有学生编号等于零,是吗?
0赞 irohit786 8/29/2022
是的,对我来说,拒绝 0 似乎是可能的解决方案,但类型提示似乎要好得多,直到我意识到它也可以给出 500

答:

1赞 Marcin Orlowski 8/29/2022 #1

您的代码需要一些规范化,如果您明确要求,则应在收到值的位置(很可能在控制器中)进行所有验证/清理和强制转换。如果由于任何原因无法正确执行有效值,则该值应从该位置飞起,或者您应该停在那里。因此,我建议您在方法中坚持严格的类型提示,因为这是减少潜在问题的好方法。至于导致值的转换问题,您首先应确保这是有效的数字字符串。有一些函数可以做到这一点,is_numeric() 是第一个要查看的候选者:intint0

$vals = ['1', 1, '', 'foo', true, -5];

foreach($vals as $val) {
  \var_dump($val);
  \var_dump(\is_numeric($val));
  echo PHP_EOL;
}

生产

string(1) "1"
bool(true)

int(1)
bool(true)

string(0) ""
bool(false)

string(3) "foo"
bool(false)

bool(true)
bool(false)

int(-5)
bool(true)

或者,您可以只对模式进行模式匹配,并且仅在输入数据匹配时才进行强制转换,更不用说对最终整数值进行一些验证了(即我认为您不允许 ID 等为负值)。\d+

评论

0赞 irohit786 8/29/2022
所有值都直接在此函数中接收,因此我只能在此处进行所有检查和验证。
1赞 Marcin Orlowski 8/30/2022
嗯,这没什么区别吗?只是如果你在 8.1 上,我可能会用联合来键入提示,然后仍然这样做,以及上面描述的所有东西。或者只是这样可以节省,至少让我控制如果我被输入错误的数据类型而不是得到string|intis_numeric()is_string()mixedTypeError