如何在PHP中实现_isset()魔术方法?

如何在PHP中实现_isset()魔术方法?,php,class,isset,magic-methods,Php,Class,Isset,Magic Methods,我试图使函数empty()和isset()处理方法返回的数据 到目前为止,我所拥有的: abstract class FooBase{ public function __isset($name){ $getter = 'get'.ucfirst($name); if(method_exists($this, $getter)) return isset($this->$getter()); // not working :( // Fatal

我试图使函数
empty()
isset()
处理方法返回的数据

到目前为止,我所拥有的:

abstract class FooBase{

  public function __isset($name){
    $getter = 'get'.ucfirst($name);
    if(method_exists($this, $getter))
      return isset($this->$getter()); // not working :(
      // Fatal error: Can't use method return value in write context 
  }

  public function __get($name){
    $getter = 'get'.ucfirst($name);
    if(method_exists($this, $getter))
      return $this->$getter();
  }

  public function __set($name, $value){
    $setter = 'set'.ucfirst($name);
    if(method_exists($this, $setter))
      return $this->$setter($value);
  }

  public function __call($name, $arguments){
    $caller = 'call'.ucfirst($name);
    if(method_exists($this, $caller)) return $this->$caller($arguments);   
  }

}
用法:

class Foo extends FooBase{
  private $my_stuff;

  public function getStuff(){
    return $this->my_stuff;
  }

  public function setStuff($stuff){
    $this->my_stuff = $stuff;
  }
}


$foo = new Foo();

if(empty($foo->stuff)) echo "empty() works! \n"; else "empty() doesn't work:( \n";
$foo->stuff = 'something';
if(empty($foo->stuff)) echo "empty() doesn't work:( \n"; else "empty() works! \n";

如果出现以下情况,我如何将其设置为空/isset返回true/false:

  • 上面的
    my_stuff
    未设置,或者在
    empty()的情况下为空或零值
  • 该方法不存在(不确定是否需要,因为我认为您无论如何都会遇到致命错误)

由于这些行,您的代码返回错误:

if(method_exists($this, $getter))
return isset($this->$getter());
您可以将其替换为:

if (!method_exists($this), $getter) {
    return false; // method does not exist, assume no property
}
$getter_result = $this->$getter();
return isset($getter_result);
如果未定义getter或返回
NULL
,则返回false。我建议您最好考虑确定某些属性设置与否的方式

上面的代码还假设您正在为所有属性创建getter,因此当没有getter时,该属性被假定为未设置

还有,为什么要使用getter?他们似乎有点过分了

public function __isset($name){
    $getter = 'get'.ucfirst($name);
    return method_exists($this, $getter) && !is_null($this->$getter());
}

这将检查
$getter()
是否存在(如果不存在,则假定该属性也不存在),并返回非空值。因此,
NULL
将导致它返回false,正如您在阅读php手册之后所期望的那样。

还有一个不依赖getter的选项

public function __isset($name)
{
    $getter = 'get' . ucfirst($name);
    if (method_exists($this, $getter)) {
        return !is_null($this->$getter());
    } else {
        return isset($this->$name);
    }
}

isset(…)
只对值有效,而不对返回值的函数有效。请参阅备注部分:如果您有普通的getter和setter,请不要使用magic\uuuu get和\uuuu set。访问器的存在完全是为了避免使用公共属性(因为这违反了封装)。如果属性
NULL
我会说它没有设置,那么
isset()
正确地返回false。使用getter和setter似乎有些过分,但它们确实允许重构应用程序的某些部分,而不会破坏其他内容。@Arjan Correct,
NULL
makes
isset()
return
false
。现在我也看到,
isset($foo->stuff)
有一些原因。简而言之:因为
$foo->stuff
实际上是基于
$foo->my_stuff
的东西,但是由getter处理。好吧,我按照你的建议,最终只对真正需要它们的两个变量使用getter/setter,其余的我创建了普通的get/setVariable()函数(我几乎对所有私有变量都使用了它们)@Alex所说的“getter”或“setter”,是指函数获取变量或函数设置变量。如果我理解正确的话,现在您实际上对所有变量使用getter和setter。但是好的,如果您需要getter和setter,就使用它们吧-我很高兴您浏览了您的代码并以您认为现在更好的方式重新设计了它:)是的,我仍然对所有变量使用getter/setter,但只有其中两个我使用了uu set/u get magic方法:)这是因为这两个变量是对象,我认为更自然的调用方式是
$foo->objectvariable->somemethod
而不是$foo->getObjectvariable()->somemethod`+1 Short and clean:)唯一应该添加的是
$This->$getter()==null
快!is_null($this->$getter())
:)速度更快,但差异非常小。是否使用
!==空
!is_null()
是品味问题,而不是速度优化问题。我再次同意:)差别很小,更多的是品味问题+如果您愿意,1也会对您有所帮助,为了便于阅读,您可以省略else。(由于if提前返回,您可以放心地执行此操作)