2010-07-10 1 views
3

Следующая «проблема»PHP getter/setter to array

PHP класс с большим количеством свойств. Много Getters/Setter.

Есть ли хорошее решение для преобразования всех свойств в массив?

protected $name; 
protected $date; 

public function getName(); 
public function getDate(); 
public function asArray(); // call all getters? 
+0

Вы спрашиваете о встроенном классе, библиотечном коде или вашем собственном? – Kris

ответ

9

уже определен ваш API и вы застряли с GetX и Setx методами? Я предпочитаю свойства. Меньшая типизация, лучшее различие между свойствами и методами и полученный код больше похожи на PHP и меньше похожи на Java. Но разоблачение свойств не означает, что вы теряете инкапсуляцию и делаете все свои внутренности общедоступными. С помощью методов __get и __set magic вы можете иметь довольно тонкий контроль над тем, что вы представляете. Кроме того, было бы довольно тривиально сбросить свойства как массив:

class Foo 
{ 
    protected $properties; 

    public function __construct() { 
     $this->properties = array(); 
    } 

    public function __set($prop, $value) { 
     $this->properties[$prop] = $value; 
    } 

    public function __get($prop) { 
     return $this->properties[$prop]; 
    } 

    public function toArray() { 
     return $this->properties; 
    } 
} 

Увы, если вы застряли с сеттеры/добытчиками из-за причудами босса или некоторого непонимания того, что ООП должно быть, почему не просто бросать объект в массив?

class Bar 
{ 
    public $x; 
    public $y; 
    public $z; 
    protected $a; 
    protected $b; 
    protected $c; 
    private $q; 
    private $r; 
    private $s; 

    public function __construct() { 
    } 

    public function setA($value) { 
     $this->a = $value; 
    } 

    public function getA() { 
     return $this->a; 
    } 

    public function setB($value) { 
     $this->b = $value; 
    } 

    public function getB() { 
     return $this->b; 
    } 

    public function setC($value) { 
     $this->c = $value; 
    } 

    public function getC() { 
     return $this->c; 
    } 

    public function toArray() { 
     return (array)$this; 
    } 
} 

Обратите внимание, как общественности, защищенные и частные свойства отлиты:

$bar = new Bar(); 
print_r($bar->toArray()); 

array(9) { 
    ["x"]=> 
    NULL 
    ["y"]=> 
    NULL 
    ["z"]=> 
    NULL 
    [" * a"]=> 
    NULL 
    [" * b"]=> 
    NULL 
    [" * c"]=> 
    NULL 
    [" Foo q"]=> 
    NULL 
    [" Foo r"]=> 
    NULL 
    [" Foo s"]=> 
    NULL 
} 

Обратите внимание, что ключи массива для защищенного/частного не начинаться с пробела, это нуль. Вы можете повторно ввести их, или даже отфильтровать защищенные/частные свойства, если вам нравится:

public function toArray() { 
    $props = array(); 
    foreach ((array)$this as $key => $value) { 
     if ($key[0] != "\0") { 
      $props[$key] = $value; 
     } 
    } 
    return $props; 
} 

Вы работаете с динамическим языком; воспользуйтесь этим и наслаждайтесь!

+2

+1 для подхода с типом. Я не согласен с неправильным использованием __get/__ set for getter/setters. – Gordon

0

Одним из вариантов было бы создать массив в конструкторе. Вы будете иметь один поглотитель и один сеттер .. Если вы хотите установить или получить что-то, сделать что-то вроде:

$foo->get('UID'); //(to get user id) 
or 
$foo->set('UID', 5); // to set something) 
2

Постарайся смотреть в get_object_vars(), get_class_vars и другие в той же категории. Примеры, показанные там, похожи на то, что вам нужно. Проверьте комментарии там (например, http://www.php.net/manual/en/function.get-class-vars.php#87772), они уже предоставляют способы, которые отвечают вашим потребностям.

+0

+1 самый простой подход imho – Gordon

3

Как об использовании ReflectionClass и ReflectionMethod, что-то вроде этого:

class PropertyHolder 
{ 
    private $name; 
    private $date; 
    private $anotherProperty; 

    public function __construct($name, $date) 
    { 
     $this->name = $name; 
     $this->date = $date; 
    } 

    public function getName() 
    { 
     return $this->name; 
    } 

    public function getDate() 
    { 
     return $this->date; 
    } 

    public function asArray() 
    { 
     $result = array(); 

     $clazz = new ReflectionClass(__CLASS__); 
     foreach ($clazz->getMethods() as $method) { 
      if (substr($method->name, 0, 3) == 'get') { 
       $propName = strtolower(substr($method->name, 3, 1)) . substr($method->name, 4); 

       $result[$propName] = $method->invoke($this); 
      } 
     } 

     return $result; 
    } 
+0

+1 Вы избили меня почти идентичным решением всего за несколько секунд :-) – Mike

2

Простой (array) бросок на $this будет достаточно:

(array) $this; 

Если у вас есть дополнительные свойства (частные, например, что не должно быть ToArray() ред), вы можете потом сбросить эти:

public function toArray() { 
    $array = (array) $this; 
    unset($array['private'], $array['privateagain']); 
    return $array; 
}