发出API GET请求时,如何在Symfony 4中使用URL和路由返回特定数据?

时间:2019-06-15 09:10:15

标签: symfony symfony4 symfony-routing

我是Symfony的新手,正在尝试学习基础知识。我最近看到了this question,并且想了解路由的工作原理。因此,我从问题中复制了Controller1.php,并将其更改为UserController.php

<?php


namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;

class UsersController extends AbstractController
{
    /**
     * @Route("/listOf/Users", methods={"GET"})
     * @param Request $request
     * @return JsonResponse
     */
    public function list(Request $request)
    {
        if (empty($request->headers->get('api-key'))) {
            return new JsonResponse(['error' => 'Please provide an API_key'], 401);
        }

        if ($request->headers->get('api-key') !== $_ENV['API_KEY']) {
            return new JsonResponse(['error' => 'Invalid API key'], 401);
        }

        return new JsonResponse($this->getDoctrine()->getRepository('App\Entity\User')->findAll());
    }
}

如OP所言,确实可以正常工作并返回以下列表(使用Sequel Pro手动添加的数据)列表:

    [
    {
        "id": 14,
        "name": "user1 Name"
    },
    {
        "id": 226,
        "name": "user2 Name"
    },
    {
        "id": 383,
        "name": "user3 Name"
    }
    ]

所以我的下一步是学习如何调整用户列表,以返回具有给定id的特定用户。因此,我遵循了official Symfony Docs on Routing。所以我将代码更改为以下内容:

<?php


namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;

class UsersController extends AbstractController
{
    /**
     * @Route("/listOf/Users/{IdUser}", requirements={"IdUser"="\d+"},  methods={"GET"})
     * @param Request $request
     * @param int $IdUser
     * @return JsonResponse
     */
    public function list(Request $request, int $IdUser)
    {
        if (empty($request->headers->get('api-key'))) {
            return new JsonResponse(['error' => 'Please provide an API_key'], 401);
        }

        if ($request->headers->get('api-key') !== $_ENV['API_KEY']) {
            return new JsonResponse(['error' => 'Invalid API key'], 401);
        }

        return new JsonResponse($this->getDoctrine()->getRepository('App\Entity\User\{IdUser}')->findAll());
    }
}

并尝试请求ID为14的用户数据,但这无效,并产生以下错误:

  

App \ Entity \ User {IdUser}类不存在(500内部服务器错误)

我还需要做些什么更改才能完成我想做的事情?

这是我的User.php实体:

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\UserRepository")
 */
class User implements \JsonSerializable
{

    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $name;

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getName(): ?string
    {
        return $this->name;
    }

    public function setName(string $name): self
    {
        $this->name = $name;

        return $this;
    }

    public function jsonSerialize()
    {
        return get_object_vars($this);
    }
}

我的UserRepository.php除了自动生成的代码外什么也没有。

编辑:我的第一个有效的请求格式为:http://domainName.local:80/listOf/Users,第二个是:http://domainName.local:80/listOf/Users/14

1 个答案:

答案 0 :(得分:1)

如先前所承诺的-这就是为什么它不起作用以及如何使其起作用。

让我们检查一下代码的打击:

$this->getDoctrine()->getRepository('App\Entity\User\{IdUser}')->findAll();

基本上您是在说:学说,给我负责处理的存储库 从字面上看,实体App\Entity\User\{IdUser}并不存在这样的实体类。 您真正想要的是App\Entity\User的仓库。

您传递给getRepository()方法的字符串必须始终是实体的全限定类名-句点。 为了确保您在这里没有任何错字,使用实体的类常量非常有帮助,

$repo = $this->getDoctrine()->getRepository(App\Entity\User::class);

一旦有了存储库,就可以调用其不同的方法,如此处的学说文档所示https://www.doctrine-project.org/api/orm/latest/Doctrine/ORM/EntityRepository.html 在您的情况下,您具有变量$IdUser,您希望将其映射到用户类的db列/实体属性id。 既然您知道您确实想要这个ID为14的用户,那么您要做的就是告诉仓库精确地找到一个看起来像这样的用户。

// here's the example for your specific case
$user = $repo->findOneBy(['id' => $IdUser]);

// another example could be e.g. to search a user by their email address
$user = $repo->findOneBy(['email' => $email]);

// you can also pass multiple conditions to find*By methods
$user = $repo->findOneBy([
    'first_name' => $firstName,
    'last_name' => $lastName,
]);

希望这比混淆=)更有用