Dynamically add a private property to an object

后端 未结 4 1451
感动是毒
感动是毒 2020-12-11 19:40

I have a class:

class Foo {
    // Accept an assoc array and appends its indexes to the object as property
    public function extend($values){
        forea         


        
相关标签:
4条回答
  • 2020-12-11 19:49

    You could do something like this.

    The __get function will check if the given key is set inside the private property.

    class Foo {
    
    private $data = array();
    
    // Accept an array and appends its indexes to the object as property
    public function extend($values){
        foreach($values as $i=>$v){
            if(!isset($this->$i))
                $this->data[$i] = $v;
        }
    }
    
    public function __get($key) {
        if (isset($this->data[$key])) {
            return $this->data[$key];
        }
    }
    
    }
    
    0 讨论(0)
  • 2020-12-11 19:51

    I would work with the whole array:

    $Foo = new Foo;
    $Foo->setOptions(array('name' => 'Bee'));
    
    class Foo {
        private $options = array();
    
        public function setOptions(array $options) {
            $this->options = $options;
        }
    
        public function getOption($value = false) {
            if($value) {
                return $this->options[$value];    
            } else {
                return $this->options;
            }
        }
    }
    

    Then you have more options when you need other values and you can iterate through the array and work with them. When you have single variable in most cases its a bit complecated.

    0 讨论(0)
  • 2020-12-11 19:58

    Here is an accessor based approach:

    class Extendible
    {
        private $properties;
    
        public function extend(array $properties)
        {
            foreach ($properties as $name => $value) {
                $this->properties[$name] = $value;
            }
        }
    
        public function __call($method, $parameters)
        {
            $accessor = substr($method, 0, 3);
            $property = lcfirst(substr($method, 3));
            if (($accessor !== 'get' && $accessor !== 'set')
                    || !isset($this->properties[$property])) {
                throw new Exception('No such method!');
            }
            switch ($accessor) {
                case 'get':
                    return $this->getProperty($property);
                    break;
                case 'set':
                    return $this->setProperty($property, $parameters[0]);
                    break;
            }
        }
    
        private function getProperty($name)
        {
            return $this->properties[$name];
        }
    
        private function setProperty($name, $value)
        {
            $this->properties[$name] = $value;
            return $this;
        }
    }
    

    Demo:

    try {
        $x = new Extendible();
        $x->extend(array('foo' => 'bar'));
        echo $x->getFoo(), PHP_EOL; // Shows 'bar'
        $x->setFoo('baz');
        echo $x->getFoo(), PHP_EOL; // Shows 'baz'
        echo $x->getQuux(), PHP_EOL; // Throws Exception
    } catch (Exception $e) {
        echo 'Error: ', $e->getMessage(), PHP_EOL;
    }
    
    0 讨论(0)
  • 2020-12-11 20:12

    Just plain, bad design.

    What's the purpose of adding a private [!] field at runtime? Existent methods can't rely on such added fields, and you'd be messing with the object functionality.

    If you want your object to behave like an hashmap [i.e. you can just call $obj -> newField = $newValue], consider using magic __get and __set methods.

    0 讨论(0)
提交回复
热议问题