2013-10-18 105 views
1

什么是检查实例变量是否从未分配的好方法?考虑下面的例子。 $this->foo为空即可开始。如果在数据库中找到$this->foo,则后续调用getFoo()将不会查询数据库。但是,如果数据库中没有任何内容被返回(null),所有后续调用仍然会触发数据库..不好。php检查是否声明了实例变量但未分配实例变量

class FooBar 
{  
    protected $foo; 
    protected $db;  

    public function getFoo() 
    { 
    if (is_null($this->foo)) { 
     $this->foo = $this->db->getFooFromDatabase(); 
    } 

    return $this->foo; 
    } 
} 
+0

我认为你需要使用一个虚拟值而不是null ......这样你可以区分“未设置”和“空”。 – mpen

+0

@标记我认为你是对的。不知道是否有一个流行的价值/对象/不断这样做 – David

回答

1

这是一个黑客,我猜,但如何不简单不设置它呢?然后只需检查对象是否具有该属性。

class FooBar 
{ 
    //REMOVED 
    //protected $foo; 
    protected $db;  

    public function getFoo() 
    { 
    if (! property_exists($this, 'foo')) { 
     $this->foo = $this->db->getFooFromDatabase(); 
    } 

    return $this->foo; 
    } 
} 
+0

'isset'也检查它是否为空......我不认为这会工作。 – mpen

+1

你说得对,我相信'property_exists'就是为此而设计的。编辑。 – SolarBear

1

没有办法做到保持一个单独的“迄今分配的”布尔标志的短缺。在大多数情况下,默认值(如在这种情况下,通常为null)充当哨兵,我不明白为什么它不能在这个例子中服务。您可以让您的查询方法返回false找不到foo,或者您可以保持原样并使用false作为属性的初始值。

我会建议第一种方法:在查询数据库后返回null大部分时间没有意义,通常语义null是“未知”。由于仅仅查询数据库,所以即使知识是“没有任何东西”,代码也知道

+2

我想他是说''foo'可能会在数据库中设置,但它被设置为'null'。他无法区分“未设置”和“foo为空”,因为默认情况下foo为空。 – mpen

+0

@Mark:然后可以用其他方式完成,使用其他常量值作为占位符。这可能是'false',它可以用'const UNKNOWN = false'和'protected $ foo = self :: UNKNOWN'来语义加强。 – Jon

+1

我不会使用'false'作为未知的;我会创建一个完整的虚拟单例类,以便它拥有自己的类型。我认为ASP.NET MVC使用他们的'DbNull'类。 – mpen