【问题标题】:Symfony 4, find() an entitySymfony 4,find() 一个实体
【发布时间】:2018-12-09 12:05:25
【问题描述】:

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

但是当我调用 setProduit() 方法(来自 Paniers 实体)时,Phpstorm 对 $produitSelected 说“预期的 App\Entity\Paniers,得到了对象”。

我不知道为什么 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;
  }
}

【问题讨论】:

    标签: php symfony controller entity symfony4


    【解决方案1】:

    你首先需要修复代码:

    不要注入 $id,你只需要输入你的实体:https://symfony.com/doc/current/best_practices/controllers.html#using-the-paramconverter

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

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

    使用英语,这是始终的规则。不仅其他人可以帮助您,还因为 Symfony 理解它,当您开始使用表单集合时,您将需要它:https://symfony.com/doc/current/form/form_collections.html

    注入存储库,您将更容易自动完成和发现错误。使用 ```make:entity` 命令,你会看到我的想法,很难解释。

    【讨论】:

    • 1) 谢谢你 2-3) 我的老师给我发了 $doctrine/$twig 的样本,所以我从坏习惯开始,但实际上是在路上 4) 我有旧表格(完整的 php)但我会在接下来的几个小时内改变它,所以很高兴知道
    【解决方案2】:

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

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

    要使其正常工作,您应该使用带有完整命名空间的Produit,或者直接在类型提示中添加命名空间。

    当然,这并不能保证或确保实际类型为Produit。所以,如果你犯了错误,PhpStorm 会报错类型。

    【讨论】:

      【解决方案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 也一样吗?
      • 解决这个特定问题有不同的方法 :) Denis V 提到了其中一个,我只是想添加另一个。当然 - 对于您想要使用的每个实体,您都可以将相应的存储库注入到控制器方法中。这样 phpstorm 将始终知道返回的对象的类型。不要忘记输入自定义存储库方法 - 如果您创建了任何方法。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多