【问题标题】:Symfony2 and Doctrine with empty relationSymfony2 和空关系的学说
【发布时间】:2013-12-01 10:28:54
【问题描述】:

我刚开始学习 Symfony2(我没有太多的 php 经验),所以我的问题对某些人来说可能看起来很有趣。我现在关注 The Book 的 Databases and Doctrine 部分,我的问题涉及 Fetching Related Objects 示例(我使用的代码与文档中的代码相同,因此我不会在此处粘贴所有代码)。

本例中有一段代码获取关联对象:

public function showAction($id)
{
    $product = $this->getDoctrine()->getRepository('AcmeStoreBundle:Product')->find($id);
    $categoryName = $product->getCategory()->getName();

    return array('product' => $product, 'category' => $categoryName);
}

当我在数据库中设置了类别引用的 Product 对象上运行此控制器时,一切正常。不幸的是,当 category 为 null 时,它会抛出 “FatalErrorException: Error: Call to a member function getName() on a non-object”

我知道这是因为没有 Category 对象,所以没有 Category 名称,但我的问题是处理这种情况的最佳方法是什么?我希望 $categoryName 返回 null 或空字符串以在我的模板中使用,就像 Product 对象的任何其他未设置属性一样,但由于它来自关联对象,所以我被困在这个问题上

【问题讨论】:

    标签: php symfony doctrine-orm


    【解决方案1】:

    您可能期望:如果$product 没有类别,则调用$product->getCategory() 时,它返回空类别。

    如果是这样,让我们​​编写代码。

    构造函数应该是:

    class Product
    {
        /**
         * @var Category $category
         */
        private $category; //clearly mentions that Product has ONE category
    
        public function __construct()
        {
            $this->category = new Category();
            //initialize this so $this->category is no longer a non-object
        }
    }
    

    编辑:

    你仍然会遇到同样的错误,因为该学说只是将记录同步到类映射中

    $product = new Product();
    $product->setName();
    ...
    $product->setCategory(null); // product has no category, so set null
    ...
    

    很抱歉,我可能对你说谎了。

    虽然学说确实像上面那样,但有两个解决建议:

    1. 修改getter

      “如果产品没有类别,则返回空类别”的其他表达式

      public function getCategory()
      {
          if (null !== $this->category) {
              return $this->category;
          }
      
          return new Category();
      }
      
    2. 将这样的“ifnull-then”逻辑移动到 twig 中(正如其他人所说)

      在控制器中:

      public function showAction($id)
      {
          $product = $this->getDoctrine()->getRepository('AcmeStoreBundle:Product')->find($id);
          //$categoryName = $product->getCategory()->getName();
      
          return array('product' => $product);
      }
      

      在模板中:

      ...
      {{ product.category.name|default('no category') }}
      ...
      

      default('no category') 可以解决问题。 它在以下情况下返回“无类别”:

      • 当内部发生错误时(您所面临的“从非对象获取属性”)
      • 如果 $product->getCategory()->getName() 为假(空字符串、null、0 等)

    对我来说,我通常更喜欢 2 而不是 1,因为它用更少的代码完成。

    【讨论】:

    • 这听起来像我想要的,但不幸的是,即使我将它添加到我的产品类中,我仍然会得到“调用非对象上的成员函数 getName()”
    • 那么,学说的内部肯定做了一些你没有预料到的事情。您能否更新您的帖子以显示产品和类别的完整代码?
    • 啊,不需要,因为您说它已记录在案!我会尝试阅读它们
    【解决方案2】:

    您是否在__construct 中初始化了category 属性?

    public function __construct(){
        ....
        $this->category = new ArrayCollection();
        ....
    }
    

    【讨论】:

    • 最初,我只在category构造函数中初始化了products属性。现在我尝试在product 中对category 做同样的事情,但结果是一样的。顺便问一下,真的需要吗? Category 是 Product 的 ManyToOne 关系,为什么需要 ArrayCollection?
    • 你是对的,我的错。如果是ManyToOne,则不需要。
    猜你喜欢
    • 2017-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-29
    • 2013-04-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多