动态集&使用__call或__get& __组?

时间:2013-09-19 16:28:06

标签: php getter-setter magic-methods

我不喜欢拥有数百个天真的Setter和Getters,但我希望能够获得一些数据的Setter和Getters,因为我可能需要对它们进行消毒等。

我有两个想法如何做到这一点:

class Test {
  private $value = "Value received from: ";
  private $value2 = "Value2 received from: ";

  function __get($property) {
    if (method_exists($this, "get".$property)) {
      return $this->getValue();
    }

    return $this->$property."__get()";
  }

  public function getValue() {
    return $this->value."getValue()";
  }
}

$obj = new Test();
echo $obj->value; // Returns: Value received from: getValue()
echo $obj->value2; // Returns: Value2 received from: __get()

class Test {
  private $value = "Value received from: ";
  private $value2 = "Value2 received from: ";

  public function __call($method, $args) {
    if (substr($method, 0, 3) == "get") {
      // Sanitizing so no functions should get through
      $property = preg_replace("/[^0-9a-zA-Z]/", "", strtolower(substr($method, 3)));

      if (isset($this->$property)) {
        return $this->$property."__call";
      }
    }
  }

  public function getValue() {
    return $this->value."getValue()";
  }
}

$obj = new Test();
echo $obj->getValue(); // Returns: Value received from: getValue()
echo $obj->getValue2(); // Returns: Value2 received from: __call

基本上唯一的区别在于魔术方法__call__get。我遗漏了__set,因为很明显我会怎么做。

真正的问题是哪一个更好?性能?可读性?安全

2 个答案:

答案 0 :(得分:2)

根据PHP Manual: Overloading,魔术方法__get()用于重载属性,而__call()用于方法。由于您正在使用方法,因此应使用适合其设计用途的方法。因此,对于可读性__call()获得了我的投票。

安全性而言,我认为任何重载都是同样安全的,也就是说根本不是真的,因为它是关于创建未明确声明的属性和方法

我还没有测试过它的 Performance 方面。我认为方法__call()会更好,因为它是为方法使用而设计的,但您可能需要microtime(true)几个测试以确定它是否重要。

老实说,我不使用__call()因为我没有需要在我的应用程序中重载方法,否则应该说我总是在我的对象类中声明方法。

答案 1 :(得分:-1)

使用__call:

class AbstractEntity
{
  /**
   * Overloading.
   *
   * Esse método não é chamado diretamente. Ele irá interceptar chamadas
   * a métodos não definidos na classe. Se for um set* ou get* irá realizar
   * as ações necessárias sobre as propriedades da classe.
   *
   * @param string $metodo O nome do método quer será chamado
   * @param array $parametros Parâmetros que serão passados aos métodos
   * @return mixed
   */
  public function __call($metodo, $parametros)
  {
    $prefixo = substr($metodo, 0, 3);
    $var = String::camelcase2underscore(strtolower(substr(str_replace($prefixo, '', $metodo), 0, 1)) . substr($metodo, 4, strlen($metodo)));

    if (property_exists($this, $var)) {

        // se for set*, "seta" um valor para a propriedade
        if (strcasecmp($prefixo, 'set') == 0) {

            $this->$var = $parametros[0];
       // se for get*, retorna o valor da propriedade
        } elseif (strcasecmp($prefixo, 'get') == 0) {

            return $this->$var;
        }
    } else {

        echo 'Propriedade ' . $var . ' não existe.';
    }
  }

  public static function camelcase2underscore($name){

    return strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', $name));    
  }
}

示例:

class usuario extends AbstractEntity
{

    protected $nm_usuario;
}


$usuario = new Usuario();
$usuario->setNmUsuario('aparagerebacanga');
echo $usuario->getNmUsuario(); //print "aparagerebacanga"