开发者

read-only properties in PHP?

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

echo $objObject->arrArray[0];

But I don't want to be able to write to those arrays after they're constructed. It feels like a PITA to construct a local variable:

$arrArray = $objObject->getArray1();
echo $arrArray[0];

And anyways, while it keeps the array in the object pristine, it doesn't prevent me from re-writing the local array variable开发者_如何学Python.


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


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


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.


For PHP 8.1+, you can use readonly properties:

class Test
{
    public readonly array $arrArray;

    public function __construct()
    {
          $this->arrArray = [1, 2, 3];
    } 
}

$test = new Test();
var_dump($test->arrArray); // OK
$test->arrArray = [4, 5, 6]; // Error


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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜