【问题标题】:Postman can't access my Symfony "PUT" Route properlyPostman 无法正确访问我的 Symfony“PUT”路由
【发布时间】:2021-04-12 16:01:13
【问题描述】:

我查看了很多地方,但我的 PUT 路线无法正常工作。我只是想让我的 PUT 路由编辑路由中指定的文章的 id,这是我的路由的样子:

/**
 * @return Response
 * @Route("/{id}", methods={"PUT"})
 * @param $id
 * @param Request $request
 */
public function edit($id, Request $request): Response
{
    $em = $this->getDoctrine()->getManager();
    $article = $em->find(Article::class,$id);
    if ($article)
    {
        $request->request->add(["article" => json_decode($request->getContent(), true)]);
        $form = $this->createForm(ArticleType::class, new Article())->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid())
        {
            $article->setNom($form["nom"]->getData());
            $article->setDescription($form["description"]->getData());
            $article->setPrix($form["prix"]->getData());
            $em->refresh($article);
            return $this->json($article, 205);
        }
        return $this->json(["error" => "Bad request"], 400);
    }
    return $this->json(["error" => "Not Found"], 404);
}

这对我来说似乎很好,但对 Postman 来说却不是,尽管它并不完全糟糕,因为它确实进入了代码!但它返回 400 错误代码,所以我认为这意味着它不会进入第二个 if 并且我不明白为什么,因为我为我的 DELETE 路由使用了类似的设置。我正在尽最大努力了解路由的工作原理,但对于 PUT,即使经过数小时的搜索,我也不知所措,因此非常感谢您的帮助!

如果需要,这里是控制器代码的其余部分。是的,我确实告诉我的订阅者允许“PUT”路由。另外,这是我的第一篇文章,我希望它足以满足本网站的标准,并感谢任何愿意给我一点时间的人!

    <?php

namespace App\Controller;

use App\Entity\Article;
use App\Form\ArticleType;
use App\Repository\ArticleRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

/**
 * Class ArticleController
 * @package App\Controller
 * @Route("/article")
 */
class ArticleController extends AbstractController
{
    /**
     * @return Response
     * @Route("/", methods={"GET"})
     * @param ArticleRepository $repository
     */
    public function index(ArticleRepository $repository): Response
    {
        return $this->json($repository->findAll());
    }

    /**
     * @return Response
     * @Route("/{id}", methods={"GET"})
     * @param $id
     */
    public function find($id): Response
    {
        $em = $this->getdoctrine()->getmanager();
        $article = $em->find(Article::class,$id);
        if ($article)
        {
            return $this->json($article, 201);
        }
        return $this->json(["error" => "Not Found"], 404);
    }

    /**
     * @return Response
     * @Route("/", methods={"POST"})
     * @param Request $request
     */
    public function new(Request $request): Response
    {
        $request->request->add(["article" => json_decode($request->getContent(), true)]);
        $form = $this->createForm(ArticleType::class, new Article())->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $em->persist($form->getData());
            $em->flush();
            return $this->json($form->getData(), 201);
        }
        return $this->json(["error" => "Bad request"], 400);
    }

    /**
     * @return Response
     * @Route("/{id}", methods={"DELETE"})
     * @param $id
     */
    public function delete($id): Response
    {
        $em = $this->getdoctrine()->getmanager();
        $article = $em->find(Article::class,$id);
        if ($article)
        {
            $em->remove($article);
            $em->flush();
            return $this->json($article, 205);
        }
        return $this->json(["error" => "Not Found"], 404);
    }

另外,这是我的邮递员请求

{
    "nom": "test",
    "description": "description test",
    "prix": 7
}

这里是 ArticleType.php

<?php

namespace App\Form;

use App\Entity\Article;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class ArticleType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('nom')
            ->add('description')
            ->add('prix')
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Article::class,
        ]);
    }
}

【问题讨论】:

  • 我认为您可能应该只使用symfony.com/doc/current/form/direct_submit.html ...您也应该检查$request-&gt;getContent() 确实包含您期望的内容。最后:您的 400 行应该 - 至少出于开发目的 - 从表单验证中返回实际的错误消息;o)
  • 这个错误是 Inmarelibero 建议的吗?它返回了一条可在此处查看的长消息:mediafire.com/file/4llywfhbw0qwr17/dump.txt/file 我检查了 $request->getContent() 确实有我的内容!最后,它似乎很相似,但我不明白“Task()”在这里做什么。谢谢!
  • 任务就像你的文章。您上传的文件似乎包含一个空的表单错误迭代器(您可以将扩展名重命名为 .html 并在浏览器中查看)。 $request->getContent() 为空。邮递员非常强大,您可以发送基本上无效的请求。你必须检查你想如何编码数据(原始,表单编码,......),如果是原始的,你必须发送正确的内容类型(应用程序/json)和东西。这是我对邮递员的普遍看法。我没有具体的建议,我不使用邮递员,我宁愿使用 curl ;oD POST 请求更好地定义 btw(编码)
  • 我做了应用程序/json的事情!正如我所说,它接收内容,邮递员甚至可以在 GET、POST 和 DELETE 上工作!只是不在 PUT 上,这很烦人。像其他作品一样,只是不是 PUT。

标签: symfony routes postman put


【解决方案1】:

我建议几件事:

  1. if ($form-&gt;isSubmitted() &amp;&amp; $form-&gt;isValid()) 分离成更易读和可调试的部分:
if ($form->isSubmitted()) {
  if ($form->isValid()) {
    ...
  }
}

通过这种方式,您可以更好地检查表单是否已提交和/或是否有效

您能否粘贴您通过 Postman 发送的请求正文?还有 ArticleType.php 类

  1. 永远不要像$request-&gt;request-&gt;add(["article" =&gt; json_decode($request-&gt;getContent(), true)]);那样修改原始请求

尝试寻找其他方法;你需要这个做什么?

【讨论】:

  • 好的,谢谢,我会这样做并查看您的回答和 Jakumi 的评论。这是一个简单的 PUT,我只需替换特定 ID 的现有数据,然后将我的 Postman 和 ArticleType.php 添加到原始帖子中!
  • 我的猜测是您缺少 csrf 令牌,在使用 api 时必须明确禁用该用法(您是否已经禁用它?)
  • 另外,您是否将 isSubmitted() 和 isValid() 分开?你能把 dump(form->getErrors()) 的输出贴在这里吗?
  • 在一个 if 子句中包含 isSubmitted 和 isValid 是顺便说一句的最佳实践,并且在 symfony 代码中非常常见(也在他们的文档和教程中)
  • 为了简单起见,它在文档中,如果这是最佳实践,则名为 ->isSubmittedAndValid() 的方法将存在分离在这种情况下很有用,例如,如果您必须添加一个 Flash 消息如果表单已提交但无效
【解决方案2】:

终于成功了,非常感谢大家! 以下是最终为我工作的内容:

/**
 * @return Response
 * @Route("/{id}", methods={"PUT"})
 * @param $id
 * @param Request $request
 */
public function edit($id, Request $request): Response
{
    $em = $this->getDoctrine()->getManager();
    $article = $em->find(Article::class,$id);
    if ($article)
    {
        $request->request->add(["article" => json_decode($request->getContent(), true)]);
        $form = $this->createForm(ArticleType::class, $article, array(
            'method' => 'put'
        ))->handleRequest($request);
        if ($form->isSubmitted())
        {
            if ($form->isValid()) {
                $em = $this->getDoctrine()->getManager();
                $em->persist($form->getData());
                $em->flush();
                return $this->json($form->getData(), 201);
            }
            return $this->json(["error" => "on isValid"], 400, array($form->getErrors()));
        }
        return $this->json(["error" => "on isSubmitted"], 400, array($form->getErrors()));
    }
    return $this->json(["error" => "Not Found"], 404);
}

没有 'method' => 'put' 它似乎不起作用.. 我检查它确实用这个替换了相应 ID 的数据!非常感谢大家的支持,祝大家有个美好的一天!!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-12-17
    • 2016-03-08
    • 1970-01-01
    • 2019-02-17
    • 2016-12-25
    • 2023-01-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多