tags:

views:

64

answers:

6

Following "problem"

PHP Class with a lot of propertys. A lot of Getters / Setter.

Is there any nice solution to convert all propertys to an array?

protected $name;
protected $date;

public function getName();
public function getDate();
public function asArray(); // call all getters?
+2  A: 

You could use PHP's reflection capabilities. Here's an example:

The MYYN
A: 

One option would be to create an array in your constructor. You will have one getter and one setter.. When you want to set or get something, do something like:

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

Try looking into get_object_vars(), get_class_vars and others in the same category. The examples shown there look like pretty much what you need. Check the comments there (for example http://www.php.net/manual/en/function.get-class-vars.php#87772) they already provide ways that suit your needs.

DrColossos
+1 most straightforward approach imho
Gordon
+1  A: 

How about using ReflectionClass and ReflectionMethod, something like this:

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;
    }
Jari
+1 You beat me to an almost identical solution by only seconds :-)
Mike
+3  A: 

Is your API already defined and are you stuck with getX and setX methods? I much prefer properties. Less typing, better distinction between properties and methods, and resulting code looks more like PHP and less like Java. But exposing properties doesn't mean you lose encapsulation and make all your internals public. With __get and __set magic methods you can have pretty fine-grained control over what you present. Plus, it would be rather trivial to dump the properties as an array:

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;
    }
}

Alas, if you're stuck with setters/getters because of a cranky boss or some misunderstanding of what OOP must be, why not just cast the object to an array?

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;
    }
}

Notice how public, protected, and private properties are cast:

$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
}

Note that the array keys for protected/private don't start with a space, it's a null. You can re-key them, or even filter out protected/private properties if you like:

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

You're working with a dynamic language; take advantage of that and enjoy it!

Timothy
+1 for the typecast approach. I disagree with misusing __get/__set for getter/setters though.
Gordon
A: 

A simple (array) cast on $this will suffice:

(array) $this;

If you have additional properties (private ones for example, that shall not be toArray()ed) you can afterwards unset these:

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