How to Implement a Read-Only Member Variable in PHP

How to implement a read-only member variable in PHP?

I suppose a solution, for class properties, would be to :

  • not define a property with the name that interests you
  • use the magic __get method to access that property, using the "fake" name
  • define the __set method so it throws an exception when trying to set that property.
  • See Overloading, for more informations on magic methods.

For variables, I don't think it's possible to have a read-only variable for which PHP will throw an exception when you're trying to write to it.


For instance, consider this little class :

class MyClass {
protected $_data = array(
'myVar' => 'test'
);

public function __get($name) {
if (isset($this->_data[$name])) {
return $this->_data[$name];
} else {
// non-existant property
// => up to you to decide what to do
}
}

public function __set($name, $value) {
if ($name === 'myVar') {
throw new Exception("not allowed : $name");
} else {
// => up to you to decide what to do
}
}
}

Instanciating the class and trying to read the property :

$a = new MyClass();
echo $a->myVar . '<br />';

Will get you the expected output :

test

While trying to write to the property :

$a->myVar = 10;

Will get you an Exception :

Exception: not allowed : myVar in /.../temp.php on line 19

PHP Readonly Properties?

You can do it like this:

class Example {
private $__readOnly = 'hello world';
function __get($name) {
if($name === 'readOnly')
return $this->__readOnly;
user_error("Invalid property: " . __CLASS__ . "->$name");
}
function __set($name, $value) {
user_error("Can't set property: " . __CLASS__ . "->$name");
}
}

Only use this when you really need it - it is slower than normal property access. For PHP, it's best to adopt a policy of only using setter methods to change a property from the outside.

PHP Readonly Properties or Constants?

Difference in write

One big difference is that you can't set class constants dynamically
at runtime, which you can do with readonly properties (from the
constructor).

Difference in read

There's also a big difference in how you access the two. Unless the
property is static, you will need to have an instance (and all
instances can have different values), while constants can always be
access without an instance.

Props to M. Eriksson

Add readonly property to element if php session has special value

You are mixing php ($user) with javascript (document.getElementById...). There's no real need to use javascript at all:

if ($user == 'Jim') { 
$readonly = "readonly";
} else {
$readonly = "";
}
// then, where you need an input to be readonly do:
?>
<input type="text" id="notes" <?php echo $readonly ?>>

read-only properties in PHP?

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

Making form fields conditionally read only (PHP)

You could store the value in an array, with the $row['pers'.$i.'Name'] as the key -

for($i=1; $i<=6; $i++){
if($_SESSION['userName'] != $row['pers'.$i.'Name'])
{
$readonly[$row['pers'.$i.'Name']] = ' readonly';
}
else {
$readonly[$row['pers'.$i.'Name']] = '';
}
}


Related Topics



Leave a reply



Submit