Differentiating between defined class properties being NULL and not set?

Say if I declare a bunch of class properties in my class definition but do not assign them values, how can I later on tell whether they have been set? The values are null by default so how can I know whether they’ve been set as null, rather than not being set?
eg


class SomeClass
{
	public $myVar;
}

$someObject = new SomeClass();
var_dump(is_null($someObject->myVar));// this is true because it's null by default

$someObject->myVar = null;
var_dump(is_null($someObject->myVar));// this is true because it's is set it to null!

Why does it matter? The value is null, work with that not whether it has been set or not.

I suspect she/he might be asking because null could be a valid value for the property of her/his object. So you can’t tell if it was just instantiated or if the user actually provided a value for the property (be it a value of null).

I do however, agree with you @logic_earth, in that you should treat null as not set. Same issue exists in other languages. What we do instead is track changes to the property, not whether or not their are instantiated or not. So the workflow is, load the object from your data store, persist its state (include property state), as the user makes changes, check if the update value differs from the objects prior state, mark the object as dirty (meaning changed) and store the new value.

The reason for the question is that I’m defining a bunch of getter methods for a class that will check if the property has been set and, if it has not, grab it from the database (I’m trying to be efficient with database calls), and set the property. In either case it then returns the value.
eg


function getValue()
{
	if(is_null($this->value))
	{
		$this->value = $this->getValueFromDatabase("value");
	}
	return $this->value;
}

As cpradio says, the value taken from the database could well be a null, in which case the database would be accessed every time.

I get the gist that testing is_null and isset on the property itself isn’t going to help me. I get what you’re saying about marking the property as changed. Maybe something like this?


function getValue()
{
	if(! property_exists($this, "db_value"))
	{
		$this->value = $this->getValueFromDatabase("value");
		$this->db_value=true; //registers that we've got this value from the db
	}
	return $this->value;
}

I’m not sure there’s an answer to your question, however, querying the database for each individual value is going to be more of a performance issue than loading the entire record the first time a single value is needed.

Oh sure, the database access is going to be pulling in all values. I left that part out for the sake of simplicity.

Then I think the simplest solution is to add a private field which is a boolean that stores whether the record has been fetched for not.

Yeah, that sounds like the way to go. Cheers.

I’m confused…why does it need to fetch the value of a single property from the database if it already got it from the database with the initial query?

Well it was kinda beyond the scope of what I was asking, but the class I’m doing will have many uses, be extended extensively, and may have a lot of properties. Some of the properties might be more database intensive and less frequently used, so didn’t want to load everything by default. So the easily-reached properties will be loaded in the constructor, and other properties that might require heavier database work can be grabbed from the database when required, but only once. I’m also allowing the possibility that properties may or may not have been loaded in the constructor. I’m covering a lot of possibilities here.

If a set of properties require more work then the others, you would probably be better off giving them their own object…otherwise…I don’t know…to me it sounds like, trying to fix a performance issue before there is a performance issue with incomplete data. Akin to micro-optimization. Have you profiled and assessed your concerns are correct?

There are always better ways…that don’t seem so “hacky” if you want to cal it that.

That’s something I will consider, yes.