Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can PHP dissect its own syntax?

Tags:

php

Can PHP dissect its own syntax? For example, I'd like to write a function that takes in an input like $object->attribute and says to itself:

OK, he's giving me $foo->bar, which means he must think that $foo is an object that has a property called bar. Before I try accessing bar and potentially get a 'Trying to get property of non-object' error, let me check whether $foo is even an object.

The end goal is to echo a value if it is set, and fail silently if not.

I want to avoid repetition like this:

<input value="<? if(is_object($foo) && is_set($foo->bar)){ echo $foo->bar; }?> "/>

...and to avoid writing a function that does the above, but has to have the object and attribute passed in separately, like this:

<input value="<? echoAttribute($foo,'bar') ?>" />

...but to instead write something which:

  • preserves the object->attribute syntax
  • is flexible: can also handle array keys or regular variables

Like this:

<input value="<? echoIfSet($foo->bar); ?> />
<input value="<? echoIfSet($baz['buzz']); ?> />
<input value="<? echoIfSet($moo); ?> />

But this all depends on PHP being able to tell me "what kind of thing am I asking for when I say $object->attribute or $array[$key]", so that my function can handle each according to its own type.

Is this possible?

Update

I got some good answers here and did some experimenting. Wanted to summarize.

  • The answer to my original question appears to be "no," but we did find a way to accomplish was I was trying to do. Techpriester pointed out that I could pass the string '$foo->bar' to a function and have it parse that and eval() it. Not the approach I want to take, but deserves a mention.
  • Peter Bailey pointed out that something like $foo->bar gets evaluated before getting passed to a function. I should have thought of this, but for some reason didn't. Thanks, Peter!
  • Will Vousden showed that passing $foo->$bar by reference allows the function to evaluate it, rather than having it evaluated beforehand. His function shows that isset($foo->bar) will not complain if $foo is not an object, which I didn't know.

More interestingly, his example seems to imply that PHP waits to evaluate a variable until it absolutely has to.

If you're passing something by value, then of course PHP has to determine the value right then. Like this:

$foo->bar = 'hi';
somefunction($foo->bar); // same as somefunction('hi');

But if you're passing by reference, it can wait to determine the value when it actually needs to.

Like this (following the order in which things happen):

echo ifSet($foo->bar); // PHP has not yet evaluated $foo->bar...
function ifSet(&$somevar){ // ...because we're passing by reference (&$somevar)
  // Now we're inside the function, but it still hasn't evaluated $foo->bar; it 
  // just made its local variable, $somevar, point to the same thing as $foo->bar
  if(isset($somevar)){ // Right HERE is where it's evaluated - when we need it
    return $bar;
  }
}

Thanks to everyone who responded! If I've misstated something, please let me know.

like image 218
Nathan Long Avatar asked Dec 10 '22 16:12

Nathan Long


1 Answers

You can pass it by reference:

<?php

function foo(&$bar)
{
    if (isset($bar))
    {
        echo "$bar\r\n";
    }
    else
    {
        echo "It's not set!\r\n";
    }
}

$baz = new stdClass;
$baz->test = 'test';
foo($baz->test);
foo($baz->test2);

$baz = array();
foo($baz['test3']);

?>

Note that this won't work if you try to access an object as an array or vice versa.

You shouldn't try to rely on something like this too much, though.

like image 123
Will Vousden Avatar answered Dec 24 '22 08:12

Will Vousden