Symfony2 和空关系的学说

Posted

技术标签:

【中文标题】Symfony2 和空关系的学说【英文标题】:Symfony2 and Doctrine with empty relation 【发布时间】: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 对象的任何其他未设置属性一样,但由于它来自关联对象,所以我被困在这个问题上

【问题讨论】:

【参考方案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
...

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

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

    修改getter

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

    public function getCategory()
    
        if (null !== $this->category) 
            return $this->category;
        
    
        return new Category();
    
    

    将这样的“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,则不需要。

以上是关于Symfony2 和空关系的学说的主要内容,如果未能解决你的问题,请参考以下文章

学说查询的语法错误 (Symfony2)

未定义索引:joinColumns 学说 + symfony2

Symfony2 学说清除缓存

symfony2 学说加入

Symfony2:学说“找不到驱动程序”

symfony2 / 学说:如何将 ResultSetMapping 与计数一起使用