Symfony 4,查找实体的find()方法

3
感谢symfony文档https://symfony.com/doc/current/doctrine.html#updating-an-object,我能够使用名为“Produit”的实体的get/set方法。

但是当我调用setProduit()方法(从Paniers实体)时,Phpstorm会显示“期望App\Entity\Paniers,得到Object”消息,针对$produitSelected参数。

我不知道为什么Phpstorm会这样说,因为我可以使用方法,问题出在哪里? find()返回一个实体对象,对吧?

class PaniersController extends AbstractController
{

    /**
    * @Route("/paniers/add/{id}", name="paniers.add")
    */
    public function addPanier(Request $request, Environment $twig, RegistryInterface $doctrine, $id)
    {
        $produitSelected = $doctrine->getRepository(Produit::class)->find($id);
        if (!$produitSelected) {
            throw $this->createNotFoundException(
                'Pas de produit trouvé pour l\' id : '.$id
            );
        }
        $lignePanier=$doctrine->getRepository(Paniers::class)->findOneBy(['produit' => $produitSelected, 'user' =>$this->getUser()]);
        if($produitSelected->getStock()>0){
            if ($lignePanier){
                $quantite =$lignePanier->getQuantite();
                $lignePanier->setQuantite($quantite+1);
            } else {
                $lignePanier = new Paniers();
                $lignePanier->setUser($this->getUser())
                ->setDateAjoutPanier(new \DateTime(date('Y-m-d')))
                ->setQuantite(1)
                ->setProduit($produitSelected);
            }
            $doctrine->getManager()->persist($lignePanier);
            $produitSelected->setStock($produitSelected->getStock()-1);
            $doctrine->getManager()->persist($produitSelected);
            $doctrine->getManager()->flush();
        }
    }
}

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\PaniersRepository")
 * @ORM\Table(name="paniers")
 */
class Paniers
{

//...

   /**
   * @ORM\ManyToOne(targetEntity="Produit")
   * @ORM\JoinColumn(name="produit_id", referencedColumnName="id")
   */
  private $produit;

     public function getProduit(): ?Produit
  {
      return $this->produit;
  }

  public function setProduit(?Produit $produit): self
  {
      $this->produit = $produit;
      return $this;
  }
}
3个回答

3
除了Denis V的正确答案之外,我想补充一点,你也可以像这样修改你的控制器:

public function addPanier(Request $request, Environment $twig, RegistryInterface $doctrine,ProduitRepository $produitRepository, $id)
        {
            $produitSelected = $produitRepostiory->find($id);
            //rest of the code
       }

这样,PhpStorm也会知道返回对象的类型,因为每个返回的对象都在相应的存储库中进行了类型提示。

嗯,是的,当我想要从我的存储库中使用自定义方法时,我会使用它,也许我应该每次都使用它。 那么对于$ lignePanier也是这样吗? - Ruskof
有不同的方法来解决这个具体的问题 :) Denis V提到了其中一个,我只想再补充一个。当然 - 为了使用每个实例,你可以将相应的存储库注入到控制器方法中。这样,phpstorm始终会知道返回对象的类型。别忘了对自定义存储库方法进行类型提示 - 如果你创建了任何存储库方法。 - Sebastian

3

PhpStorm似乎不太聪明,无法理解在这种情况下find($id)的返回值实际类型将是Produit。但是你可以帮助它:

/** @var Produit $produitSelected */
$produitSelected = $doctrine->getRepository(Produit::class)->find($id);

为了使其工作,您应该使用带有完整命名空间的Produit,或直接在类型提示中添加命名空间。
当然,这并不能保证实际类型将是Produit。因此,如果您犯了错误,PhpStorm 将会错误地报告类型。

2

首先需要修复代码:

不要注入 $id,你只需要在实体上使用类型提示:https://symfony.com/doc/current/best_practices/controllers.html#using-the-paramconverter

不要注入 $doctrine,使用 $em = $this->getDoctrine()->getManager();

不要注入 $twig,使用 return $this->render('...template', []);

使用英语,这是始终如一的规则。不仅其他人可以帮助你,Symfony也能够理解它,并且当你开始使用表单集合时,你将需要它:https://symfony.com/doc/current/form/form_collections.html

注入 repository,你将拥有自动完成和更容易发现错误。使用 ```make:entity``` 命令,你将看到我想表达的内容,很难解释。


  1. 谢谢你 2-3) 我的老师用$doctrine/$twig给我发了一些示例代码,所以我开始养成了一些不好的习惯,但实际上这对我来说还好。
  2. 我有旧表单(完整的PHP),但我会在接下来的几个小时内进行更改,所以知道这一点很好。
- Ruskof

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接