__get, interesting problem

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
User avatar
jwalsh
Forum Contributor
Posts: 202
Joined: Sat Jan 03, 2004 4:55 pm
Location: Cleveland, OH

__get, interesting problem

Post by jwalsh »

Hey guys,

I got an interesting result by using a magic getter on my class.

Code: Select all

public function __get($Name)
	{
		$getter='get'.$Name;
		
		if(method_exists($this,$getter))
		{
			$returnValue = $this->$getter();
		}
		else
		{
			throw new InvalidPropertyException("No Readable Property: $Name", get_class($this), $Name);
		}
		
		return $returnValue;
	}
And from outside the class...

Code: Select all

$tempProperty = $Class->Property;

if (isset($tempProperty))
{
    echo "GOT HERE";
}
... works properly, and echo's the text. However, this doesn't work...

Code: Select all

if (isset($Class->Property))
{
    echo "GOT HERE";
}
Any ideas?
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

You need to overload __isset() as well
http://de3.php.net/manual/en/language.oop5.overloading.php wrote:Since PHP 5.1.0 it is also possible to overload the isset() and unset() functions via the __isset and __unset methods respectively. Method __isset is called also with empty().
User avatar
RobertGonzalez
Site Administrator
Posts: 14293
Joined: Tue Sep 09, 2003 6:04 pm
Location: Fremont, CA, USA

Post by RobertGonzalez »

What is the visibility of the property?
User avatar
jwalsh
Forum Contributor
Posts: 202
Joined: Sat Jan 03, 2004 4:55 pm
Location: Cleveland, OH

Post by jwalsh »

volka wrote:You need to overload __isset() as well
http://de3.php.net/manual/en/language.oop5.overloading.php wrote:Since PHP 5.1.0 it is also possible to overload the isset() and unset() functions via the __isset and __unset methods respectively. Method __isset is called also with empty().
Ok... but what would I do differently? All I want to know is if it has a value or not.
User avatar
jwalsh
Forum Contributor
Posts: 202
Joined: Sat Jan 03, 2004 4:55 pm
Location: Cleveland, OH

Post by jwalsh »

Everah wrote:What is the visibility of the property?
__Get calls a public function getPropertyName();
User avatar
John Cartwright
Site Admin
Posts: 11470
Joined: Tue Dec 23, 2003 2:10 am
Location: Toronto
Contact:

Post by John Cartwright »

jwalsh wrote:
volka wrote:You need to overload __isset() as well
http://de3.php.net/manual/en/language.oop5.overloading.php wrote:Since PHP 5.1.0 it is also possible to overload the isset() and unset() functions via the __isset and __unset methods respectively. Method __isset is called also with empty().
Ok... but what would I do differently? All I want to know is if it has a value or not.
Volka's last post told you exactly what you need to do ;)
User avatar
jwalsh
Forum Contributor
Posts: 202
Joined: Sat Jan 03, 2004 4:55 pm
Location: Cleveland, OH

Post by jwalsh »

Ok. Now I am confused lol, sorry if I'm missing something obvious here.

isset() natively tells me if the parameter exists or not. That's exactly what I want it to do. Unless I'm missing something here, I need to overload isset() to do exactly the same thing it's native function does?

Code: Select all

public function __isset($Value)
{
    return isset($Value);
}
User avatar
Weirdan
Moderator
Posts: 5978
Joined: Mon Nov 03, 2003 6:13 pm
Location: Odessa, Ukraine

Post by Weirdan »

__isset accepts property name:

Code: Select all

class Tst {
  private $_something;
  public function __isset($name) {
    return isset($this->{'_' . $name});
  }
}
$obj = new Tst;
var_dump(isset($obj->something));
User avatar
jwalsh
Forum Contributor
Posts: 202
Joined: Sat Jan 03, 2004 4:55 pm
Location: Cleveland, OH

Post by jwalsh »

Ok,

I did a little bit more reading on the __isset(), as as I understand the native isset() function doesn't call the magic getter functions.

So, I've put a test case together, and confirmed that my problem still exists, even with the overloaded __isset();

Code: Select all

class Test
{
	public function __get($Name)
	{
		$getter='get'.$Name;
		
		if(method_exists($this,$getter))
		{
			$returnValue = $this->$getter();
		}
		else
		{
			throw new InvalidPropertyException("No Readable Property: $Name", get_class($this), $Name);
		}
		
		return $returnValue;
	}
	
	public function __isset($Property)
	{
		$getter='get'.$Name;
		
		if(method_exists($this,$getter))
		{
			$tempValue = $this->$getter();
			$returnValue = isset($tempValue);
		}
		else
		{
			$returnValue = false;
		}
		
		return $returnValue;
	}
	
	public function getTestProperty()
	{
		return array(5,4,3);
	}
	
}
The following returns false.

Code: Select all

$foo = new Test;

var_dump(isset($foo->TestProperty));
But, the following returns true:

Code: Select all

$foo = new Test;
$bar = $foo->TestProperty;

var_dump(isset($bar));
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

Please set error_reporting to E_ALL and either set display_errors On or keep an eye on the logfile.
You will get a Notice: Undefined variable: pointing you to the line that needs a little adjustment.
User avatar
jwalsh
Forum Contributor
Posts: 202
Joined: Sat Jan 03, 2004 4:55 pm
Location: Cleveland, OH

Post by jwalsh »

Thanks everyone. We opted to write a custom is_set() function that returns the opposite of is_null, since is_null works properly with our situation.

Thanks again.
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

If you had turned error_reporting/display_erros on it would have warned you about the simple error
public function __isset($Property)
{
$getter='get'.$Name;
Developmentsystem => error_reporting=E_ALL => many time-killing problems avoided.
User avatar
jwalsh
Forum Contributor
Posts: 202
Joined: Sat Jan 03, 2004 4:55 pm
Location: Cleveland, OH

Post by jwalsh »

Volka,

Thank you for all your help. I see the typo in there, and actually fixed it. With the error reporting on, I didn't get any messages though. In fact, the _isset() never got called. (tried to die()) on the first line of the __isset() and it never fired. I do have PHP 5.1+.

Regardless, our solution, as "hackish" as it is at the moment will suffice for now. We'll refactor it when we have time to diagnose the full cause of the problem.

Thanks again for all your help. It is appreciated.

Josh
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

Then I suspect your php installation doesn't meat the requirements for this to work.
What does

Code: Select all

<?php echo phpversion(); ?>
print?

Code: Select all

<?php
class Foo {
	public $publicprop = 1;
	private $privateprop = 1;
	
	private function get_bar() {
		return time();
	}
	
	public function __isset($name) {
		echo "__isset($name) invoked   ";
		return method_exists($this, 'get_'.$name);
	}
}

$foo = new Foo;

var_dump(isset($foo->publicprop));
var_dump(isset($foo->privateprop));
var_dump(isset($foo->bar));
var_dump(isset($foo->xyz));
?>
gives me
bool(true)
__isset(privateprop) invoked bool(false)
__isset(bar) invoked bool(true)
__isset(xyz) invoked bool(false)
Post Reply