PHP可以解析自己的语法吗?例如,我想写一个函数,它接受像$object->attribute
这样的输入并对自己说:
好的,他正在给我
$foo->bar
,这意味着他必须认为$foo
是一个具有bar
属性的对象。在我尝试访问bar
并可能获得“尝试获取非对象属性”错误之前,让我检查$foo
是否是对象。
最终目标是在设置值时回显值,如果不是则静默失败。
我想避免像这样重复:
<input value="<? if(is_object($foo) && is_set($foo->bar)){ echo $foo->bar; }?> "/>
...并且避免编写一个执行上述操作的函数,但必须单独传入对象和属性,如下所示:
<input value="<? echoAttribute($foo,'bar') ?>" />
...但而不是写下以下内容:
像这样:
<input value="<? echoIfSet($foo->bar); ?> />
<input value="<? echoIfSet($baz['buzz']); ?> />
<input value="<? echoIfSet($moo); ?> />
但这一切都取决于PHP能够告诉我“当我说$object->attribute
或$array[$key]
时,我要求的是什么样的东西,以便我的功能可以根据自己的要求处理每个类型。
这可能吗?
我在这里得到了一些好的答案并做了一些实验。想总结一下。
eval()
。不是我想采取的方法,但值得一提。$foo->bar
之类的内容进行评估。我应该想到这一点,但由于某种原因没有。谢谢,彼得!$foo->$bar
允许函数对其进行评估,而不是事先对其进行评估。他的函数显示isset($foo->bar)
如果$foo
不是一个我不知道的对象,就不会抱怨。更有趣的是,他的例子似乎暗示 PHP等待评估变量,直到绝对必须。
如果你传递按值,那么PHP当然必须确定值。像这样:
$foo->bar = 'hi';
somefunction($foo->bar); // same as somefunction('hi');
但是,如果您通过引用传递 ,它可以等待实际需要时确定该值。
像这样(遵循事情发生的顺序):
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;
}
}
感谢所有回复的人!如果我有错误的话,请告诉我。
答案 0 :(得分:6)
您可以通过引用传递它:
<?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']);
?>
请注意,如果您尝试将对象作为数组访问,则无法使用此功能,反之亦然。
不过,你不应该过分依赖这样的事情。
答案 1 :(得分:3)
也许在这个非常具体的情况下你可以使用@符号:
<input value="<?php echo @$foo->bar; ?> "/>
答案 2 :(得分:2)
你永远无法做到这样的事情
echoIfSet($foo->bar);
是因为$foo->bar
在发送到函数之前被评估了。如果该值是一个字符串,则所有echoIfSet()
都将看到一个字符串 - 它不知道该字符串来自对象的属性。
所以,没有,总之。 PHP无法“剖析自己的语法”
您拥有的每个选项(使用__get()/ __ set()或Reflection)都会涉及到比您要避免的更多的代码和工作 - 而且它们仍然无法满足您的需求。
答案 3 :(得分:2)
将数组和对象包装在特殊数组中。你可以使用php魔术方法访问属性。
class wrap implements ArrayAccess{
private $fields=array();
function __get($name){
if(isset($this->fields[$name])){
return $this->fields[$name];
}
}
function __set($name, $value){
$this->fields[$name] = $value;
}
// with function isset()
public function offsetExists($offset) {
return isset($this->$fields[$offset]);
}
public function offsetGet($offset) {
return $this->$fields[$offset];
}
public function offsetSet($offset, $value) {
return $this->$fields[$offset] = $value;
}
public function offsetUnset($offset) {
unset($this->$fields[$offset]);
}
}
这将允许你做你想做的所有事情。
答案 4 :(得分:1)
有一种语言功能可以执行任何PHP代码,并将其作为字符串传递给它:eval()
。
但你真的,真的(如“我已经死了很严重”),不应该使用它。它导致的问题比它解决的问题多得多,并使你的代码无法维护。
通常有一种更好,更清洁的方式。
“eval()”导致了力量的黑暗面,我的意思是PHP。
如果你只想要提供字符串的“obj”和“attribute”部分,正则表达式可以做到这一点。它会像"/\$(\w+)->(\w+)/"
。您可以将其提供给preg_match()
,它会为您提供字符串组件。
答案 5 :(得分:0)
您是否只是在寻找eval
声明?
答案 6 :(得分:0)
如果您正在寻找能够为您传递变量名称的内容,例如:
function foo($variable)
{
echo variableName($variable);
}
$test = "Hello World";
// echoes "test"
foo($test);
然后你不会找到它。 PHP没有这样的功能。