2

What is a good way to check if an instance variable has never been assigned. Consider the following example. $this->foo is null to start. If $this->foo is found in the database, subsequent calls to getFoo() won't query the database. However, if there is nothing in the database that gets returned(null) all subsequent calls still hit the database..not good.

class FooBar 
{    
  protected $foo;
  protected $db;    

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

    return $this->foo;
  }
}
2
  • I think you need to use a dummy value instead of null...that way you can differentiate between 'not set' and 'null'. Commented Oct 18, 2013 at 20:05
  • @Mark i think you're right. Didn't know if there's a popular value/object/constant way of doing this Commented Oct 18, 2013 at 20:32

2 Answers 2

1

This is a bit of a hack, I guess, but how about simply not setting it? Then simply check whether the object has that property.

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

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

    return $this->foo;
  }
}
Sign up to request clarification or add additional context in comments.

2 Comments

isset also checks if it's null..I don't think this will work.
You're right, and I believe property_exists is meant for that. Edited.
1

There is no way to do that short of keeping a separate "assigned thus far" boolean flag. In most cases the default value (as in this case, usually null) serves adequately as a sentinel, and I don't see why it would not be able to serve also in this example. You could have either your query method return false on not finding a foo, or you could leave it as is and use false as the initial value of the property.

I would suggest the first approach: returning null after querying the database doesn't make sense most of the time, the usual semantics of null being "not known". Since the database was just queried the code does know, even if the knowledge is "nothing's there".

5 Comments

I think he's saying that foo might be set in the DB, but it's set to null. He can't differentiate between "not set" and "foo is null" because foo is null by default.
@Mark: Then it could be done the other way, using some other constant value as a placeholder. That could be false, and it could be semantically reinforced with const UNKNOWN = false and protected $foo = self::UNKNOWN.
I wouldn't use false as the unknown either; I'd create a whole dummy singleton class so that it has its own type. I think ASP.NET MVC does with with their DbNull class.
@Mark: There's no need, if you are OK with using an object you can use any object at all (e.g. new stdClass). Comparing objects with === has reference equality semantics, so you will always be able to tell the sentinel apart. I have used this technique to good effect, but only when I absolutely had to. It's unwieldy (must set initial value inside the constructor).
I suppose you could use stdClass as your sentinel value, but then where would you store it? In a global variable? I'd prefer a getter on a static method (since PHP doesn't have static readonly values). Anyway, you're right, this might be overengineering; I like SolarBear's solution as it's simple, clear, and looks like it should work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.