read-only properties in PHP?

前端 未结 4 562
清歌不尽
清歌不尽 2021-01-17 14:18

Is there a way to make a read-only property of an object in PHP? I have an object with a couple arrays in it. I want to access them as I normally would an array

<         


        
相关标签:
4条回答
  • 2021-01-17 14:56

    Well, the question is where do you want to prevent writing from?

    The first step is making the array protected or private to prevent writing from outside of the object scope:

    protected $arrArray = array();
    

    If from "outside" of the array, a GETTER will do you fine. Either:

    public function getArray() { return $this->arrArray; }
    

    And accessing it like

    $array = $obj->getArray();
    

    or

    public function __get($name) {
        return isset($this->$name) ? $this->$name : null;
    }
    

    And accessing it like:

    $array = $obj->arrArray;
    

    Notice that they don't return references. So you cannot change the original array from outside the scope of the object. You can change the array itself...

    If you really need a fully immutable array, you could use a Object using ArrayAccess...

    Or, you could simply extend ArrayObject and overwrite all of the writing methods:

    class ImmutableArrayObject extends ArrayObject {
        public function append($value) {
            throw new LogicException('Attempting to write to an immutable array');
        }
        public function exchangeArray($input) {
            throw new LogicException('Attempting to write to an immutable array');
        }
        public function offsetSet($index, $newval) {
            throw new LogicException('Attempting to write to an immutable array');
        }
        public function offsetUnset($index) {
            throw new LogicException('Attempting to write to an immutable array');
        }
    }
    

    Then, simply make $this->arrArray an instance of the object:

    public function __construct(array $input) {
        $this->arrArray = new ImmutableArrayObject($input);
    }
    

    It still supports most array like usages:

    count($this->arrArray);
    echo $this->arrArray[0];
    foreach ($this->arrArray as $key => $value) {}
    

    But if you try to write to it, you'll get a LogicException...

    Oh, but realize that if you need to write to it, all you need to do (within the object) is do:

    $newArray = $this->arrArray->getArrayCopy();
    //Edit array here
    $this->arrArray = new ImmutableArrayObject($newArray);
    
    0 讨论(0)
  • 2021-01-17 15:05

    in the class, do this:

    private $array;
    
    function set_array($value) {
        $this->array = $value;
    }
    

    then you just set like this:

    $obj->set_array($new_array);
    
    0 讨论(0)
  • 2021-01-17 15:09

    If defined, the magic functions __get() and __set() will be called whenever a non-existing or private property is accessed. This can be used to create "get" and "set" methods for private properties, and for instance make them read-only or manipulate the data when stored or retrieved in it.

    For instance:

    class Foo
    {
      private $bar = 0;
      public $baz = 4; // Public properties will not be affected by __get() or __set()
      public function __get($name)
      {
        if($name == 'bar')
          return $this->bar;
        else
          return null;
      }
      public function __set($name, $value)
      {
        // ignore, since Foo::bar is read-only
      }
    }
    
    $myobj = new Foo();
    echo $foo->bar; // Output is "0"
    $foo->bar = 5;
    echo $foo->bar; // Output is still "0", since the variable is read-only
    

    See also the manual page for overloading in PHP.

    0 讨论(0)
  • 2021-01-17 15:16

    If you're using PHP 5+ you can do it with __set() and __get() methods.

    You have to define how they work but should do just this.

    Edit an example would be like this.

    class Example {
        private $var;
        public function __get($v) {
            if (is_array($v)) {
                foreach () {
                    // handle it here
                }
            } else {
                return $this->$v;
            }
        }
    }
    

    This might not be the "best" way of doing it but it'll work depending on what you need

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