gpt4 book ai didi

symfony - Symfony 路由中的 ID 超出范围

转载 作者:行者123 更新时间:2023-12-03 14:57:16 25 4
gpt4 key购买 nike

我有一个 Symfony Controller 的通用结构(使用 FOSRestBundle)

/**
* @Route\Get("users/{id}", requirements={"userId" = "(\d+)"})
*/
public function getUserAction(User $user)
{
}

现在,如果我请求 http://localhost/users/1一切安好。但如果我要求 http://localhost/users/11111111111111111我收到 500 错误和异常
ERROR:  value \"11111111111111111\" is out of range for type integer"

有没有办法在将 id 传输到数据库之前检查它?

作为解决方案,我可以指定 id 的长度
/**
* @Route\Get("users/{id}", requirements={"userId" = "(\d{,10})"})
*/

但随后 Symfony 会说没有这样的路由,而不是显示 id 不正确。

最佳答案

通过告诉 Symfony getUserAction()参数是 User例如,理所当然地认为 {id} url参数必须匹配as主键,交给Doctrine ParamConverter去获取对应的User .

至少有两种解决方法。

1.使用参数转换器repository_method配置

在 Controller 函数的注释中,我们可以添加 @ParamConverter注释并告诉它使用 repository_method选项。

这样,Symfony 会将 url 参数传递给我们实体 中的函数。存储库 ,从中我们将能够检查 url 参数的完整性。

UserRepository ,让我们创建一个通过主键获取实体的函数,首先检查参数的完整性。也就是说,$id不得大于 PHP 可以处理的最大整数(PHP_INT_MAX 常量)。

请注意 : $id是一个字符串,因此可以安全地将其与 PHP_INT_MAX 进行比较, 因为 PHP 会自动类型转换 PHP_INT_MAX到一个字符串并将其与 $id 进行比较.如果它是一个整数,则测试总是会失败(根据设计,所有整数都小于或等于 PHP_INT_MAX)。

// ...
use Symfony\Component\Form\Exception\OutOfBoundsException;

class UserRepository extends ...
{
// ...

public function findSafeById($id) {
if ($id > PHP_INT_MAX) {
throw new OutOfBoundsException($id . " is too large to fit in an integer");
}

return $this->find($id);
}
}

这只是一个例子:我们可以在抛出异常之前做任何我们喜欢的事情(例如记录失败的尝试)。

然后,在我们的 Controller ,让我们包含 ParamConverter注解:
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;

并修改添加注释的功能注释:
@ParamConverter("id", class="App:User", options={"repository_method" = "findSafeById"}) 

我们的 Controller 函数应该如下所示:
  /**
* @Get("users/{id}")
* @ParamConverter("id", class="App:User", options={"repository_method" = "findSafeById"})
*/
public function getUserAction(User $user) {
// Return a "OK" response with the content you like
}

这种技术允许自定义异常,但不能让您控制响应 - 在生产中您仍然会收到 500 错误。

文档:见 here .

2.解析路线“老路”

这种方式是 Symfony 3 之前唯一可行的方式,并且可以让您对生成的响应进行更细粒度的控制。

让我们像这样更改 Action 原型(prototype):
/**
* @Route\Get("users/{id}", requirements={"id" = "(\d+)"})
*/
public function getUserAction($id)
{
}

现在,在操作中,我们将收到请求的 $id我们将能够检查它是否正常。如果不是,我们抛出异常和/或返回一些错误响应(我们可以选择 HTTP 状态代码、格式和其他任何内容)。

您可以在下面找到此过程的示例实现。
use FOS\RestBundle\Controller\Annotations\Get;
use FOS\RestBundle\Controller\FOSRestController;
use Symfony\Component\Form\Exception\OutOfBoundsException;
use Symfony\Component\HttpFoundation\JsonResponse;

class MyRestController extends FOSRestController {
/**
* @Get("users/{id}", requirements={"id" = "(\d+)"})
*/
public function getUserAction($id) {

try {
if ($id > PHP_INT_MAX) {
throw new OutOfBoundsException($id . " is too large to fit in an integer");
}

// Replace App\Entity\User with your actual Entity alias
$user = $this->getDoctrine()->getRepository('App\Entity\User')->find($id);
if (!$user) {
throw new \Doctrine\ORM\NoResultException("User not found");
}

// Return a "OK" response with the content you like
return new JsonResponse(['key' => 123]);

} catch (Exception $e) {
return new JsonResponse(['message' => $e->getMessage()], 400);
}
}

关于symfony - Symfony 路由中的 ID 超出范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49650926/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com