I have a class where I'm using __set. Because I don't want it to set just anything, I have an array of approved variables that it checks before it will actually set a class property.
However, on construct, I want the __construct method to set several class properties, some of which are not in the approved list. So when construct happens, and I do $this->var = $value, I of course get my exception that I'm not allowed to set that variable.
Can I get around this somehow?
Declare the class members:
class Blah
{
private $imAllowedToExist; // no exception thrown because __set() wont be called
}
Declaring the class members is your best bet. If that doesn't work, you could have a switch ($this->isInConstructor?) which determines whether to throw the error.
On the other hand, you could also use the __get method as well as the __set method and have both of them map to a wrapped library:
class Foo
{
private $library;
private $trustedValues;
public function __construct( array $values )
{
$this->trustedValues = array( 'foo', 'bar', 'baz' );
$this->library = new stdClass();
foreach( $values as $key=>$value )
{
$this->library->$key = $value;
}
}
public function __get( $key )
{
return $this->library->$key;
}
public function __set( $key, $value )
{
if( in_array( $key, $this->trustedValues ) )
{
$this->library->$key = $value;
}
else
{
throw new Exception( "I don't understand $key => $value." );
}
}
}
Related
I know this question has been asked several times, but none of them have a real answer for a workaround. Maybe there's one for my specific case.
I'm building a mapper class which uses the magic method __get() to lazy load other objects. It looks something like this:
public function __get ( $index )
{
if ( isset ($this->vars[$index]) )
{
return $this->vars[$index];
}
// $index = 'role';
$obj = $this->createNewObject ( $index );
return $obj;
}
In my code I do:
$user = createObject('user');
$user->role->rolename;
This works so far. The User object doesn't have a property called 'role', so it uses the magic __get() method to create that object and it returns its property from the 'role' object.
But when i try to modify the 'rolename':
$user = createUser();
$user->role->rolename = 'Test';
Then it gives me the following error:
Notice: Indirect modification of overloaded property has no effect
Not sure if this is still some bug in PHP or if it's "expected behaviour", but in any case it doesn't work the way I want. This is really a show stopper for me... Because how on earth am I able to change the properties of the lazy loaded objects??
EDIT:
The actual problem only seems to occur when I return an array which contains multiple objects.
I've added an example piece of code which reproduces the problem:
http://codepad.org/T1iPZm9t
You should really run this in your PHP environment the really see the 'error'. But there is something really interesting going on here.
I try to change the property of an object, which gives me the notice 'cant change overloaded property'. But if I echo the property after that I see that it actually DID change the value... Really weird...
All you need to do is add "&" in front of your __get function to pass it as reference:
public function &__get ( $index )
Struggled with this one for a while.
Nice you gave me something to play around with
Run
class Sample extends Creator {
}
$a = new Sample ();
$a->role->rolename = 'test';
echo $a->role->rolename , PHP_EOL;
$a->role->rolename->am->love->php = 'w00';
echo $a->role->rolename , PHP_EOL;
echo $a->role->rolename->am->love->php , PHP_EOL;
Output
test
test
w00
Class Used
abstract class Creator {
public function __get($name) {
if (! isset ( $this->{$name} )) {
$this->{$name} = new Value ( $name, null );
}
return $this->{$name};
}
public function __set($name, $value) {
$this->{$name} = new Value ( $name, $value );
}
}
class Value extends Creator {
private $name;
private $value;
function __construct($name, $value) {
$this->name = $name;
$this->value = $value;
}
function __toString()
{
return (string) $this->value ;
}
}
Edit : New Array Support as requested
class Sample extends Creator {
}
$a = new Sample ();
$a->role = array (
"A",
"B",
"C"
);
$a->role[0]->nice = "OK" ;
print ($a->role[0]->nice . PHP_EOL);
$a->role[1]->nice->ok = array("foo","bar","die");
print ($a->role[1]->nice->ok[2] . PHP_EOL);
$a->role[2]->nice->raw = new stdClass();
$a->role[2]->nice->raw->name = "baba" ;
print ($a->role[2]->nice->raw->name. PHP_EOL);
Output
Ok die baba
Modified Class
abstract class Creator {
public function __get($name) {
if (! isset ( $this->{$name} )) {
$this->{$name} = new Value ( $name, null );
}
return $this->{$name};
}
public function __set($name, $value) {
if (is_array ( $value )) {
array_walk ( $value, function (&$item, $key) {
$item = new Value ( $key, $item );
} );
}
$this->{$name} = $value;
}
}
class Value {
private $name ;
function __construct($name, $value) {
$this->{$name} = $value;
$this->name = $value ;
}
public function __get($name) {
if (! isset ( $this->{$name} )) {
$this->{$name} = new Value ( $name, null );
}
if ($name == $this->name) {
return $this->value;
}
return $this->{$name};
}
public function __set($name, $value) {
if (is_array ( $value )) {
array_walk ( $value, function (&$item, $key) {
$item = new Value ( $key, $item );
} );
}
$this->{$name} = $value;
}
public function __toString() {
return (string) $this->name ;
}
}
I've had this same error, without your whole code it is difficult to pinpoint exactly how to fix it but it is caused by not having a __set function.
The way that I have gotten around it in the past is I have done things like this:
$user = createUser();
$role = $user->role;
$role->rolename = 'Test';
now if you do this:
echo $user->role->rolename;
you should see 'Test'
Though I am very late in this discussion, I thought this may be useful for some one in future.
I had faced similar situation. The easiest workaround for those who doesn't mind unsetting and resetting the variable is to do so. I am pretty sure the reason why this is not working is clear from the other answers and from the php.net manual. The simplest workaround worked for me is
Assumption:
$object is the object with overloaded __get and __set from the base class, which I am not in the freedom to modify.
shippingData is the array I want to modify a field of for e.g. :- phone_number
// First store the array in a local variable.
$tempShippingData = $object->shippingData;
unset($object->shippingData);
$tempShippingData['phone_number'] = '888-666-0000' // what ever the value you want to set
$object->shippingData = $tempShippingData; // this will again call the __set and set the array variable
unset($tempShippingData);
Note: this solution is one of the quick workaround possible to solve the problem and get the variable copied. If the array is too humungous, it may be good to force rewrite the __get method to return a reference rather expensive copying of big arrays.
I was receiving this notice for doing this:
$var = reset($myClass->my_magic_property);
This fixed it:
$tmp = $myClass->my_magic_property;
$var = reset($tmp);
I agree with VinnyD that what you need to do is add "&" in front of your __get function, as to make it to return the needed result as a reference:
public function &__get ( $propertyname )
But be aware of two things:
1) You should also do
return &$something;
or you might still be returning a value and not a reference...
2) Remember that in any case that __get returns a reference this also means that the corresponding __set will NEVER be called; this is because php resolves this by using the reference returned by __get, which is called instead!
So:
$var = $object->NonExistentArrayProperty;
means __get is called and, since __get has &__get and return &$something, $var is now, as intended, a reference to the overloaded property...
$object->NonExistentArrayProperty = array();
works as expected and __set is called as expected...
But:
$object->NonExistentArrayProperty[] = $value;
or
$object->NonExistentArrayProperty["index"] = $value;
works as expected in the sense that the element will be correctly added or modified in the overloaded array property, BUT __set WILL NOT BE CALLED: __get will be called instead!
These two calls would NOT work if not using &__get and return &$something, but while they do work in this way, they NEVER call __set, but always call __get.
This is why I decided to return a reference
return &$something;
when $something is an array(), or when the overloaded property has no special setter method, and instead return a value
return $something;
when $something is NOT an array or has a special setter function.
In any case, this was quite tricky to understand properly for me! :)
This is occurring due to how PHP treats overloaded properties in that they are not modifiable or passed by reference.
See the manual for more information regarding overloading.
To work around this problem you can either use a __set function or create a createObject method.
Below is a __get and __set that provides a workaround to a similar situation to yours, you can simply modify the __set to suite your needs.
Note the __get never actually returns a variable. and rather once you have set a variable in your object it no longer is overloaded.
/**
* Get a variable in the event.
*
* #param mixed $key Variable name.
*
* #return mixed|null
*/
public function __get($key)
{
throw new \LogicException(sprintf(
"Call to undefined event property %s",
$key
));
}
/**
* Set a variable in the event.
*
* #param string $key Name of variable
*
* #param mixed $value Value to variable
*
* #return boolean True
*/
public function __set($key, $value)
{
if (stripos($key, '_') === 0 && isset($this->$key)) {
throw new \LogicException(sprintf(
"%s is a read-only event property",
$key
));
}
$this->$key = $value;
return true;
}
Which will allow for:
$object = new obj();
$object->a = array();
$object->a[] = "b";
$object->v = new obj();
$object->v->a = "b";
I have run into the same problem as w00, but I didn't had the freedom to rewrite the base functionality of the component in which this problem (E_NOTICE) occured. I've been able to fix the issue using an ArrayObject in stead of the basic type array(). This will return an object, which will defaulty be returned by reference.
I'm trying to create a method that will allow me to set properties within a class using the setVal() function, if the user is trying to set the value from outside the class without using the 'forceSet' function then it will throw an exception.
The problem is that its throwing an exception even if the $forceSet is true. If i set the property manually in the class to have private access then everything works fine, but this is not an option as I wish to be able to set various properties in this class dynamically.
class test
{
private $_allowedCols = array('title', 'name', 'surname');
public function __set($n,$v)
{
$this->setVal($n, $v);
}
public function setVal($name, $value, $forceSet=false)
{
if (!$forceSet && !in_array($this->_allowedCols, $name))
{
throw new Exception('cant set value');
}
$this->$name = $value;
}
}
$b = new test;
$b->setVal('blah', 'test', true);
print_r($b);
exit;
What I want to be able to do is set all the values from a $_POST into properties in the object. I want to check against the $_allowedCols to make sure only values I want are being put into the object but sometimes I might want to force values in from the code that aren't in the $_allowedCols.
Any ideas?
The hacks will work but it might be cleaner to use an internal array. Something like:
class test
{
private $data = array();
public function __set($n,$v)
{
if (isset($this->data[$n])) return $this->data[$n] = $v;
throw new Exception('cant set value');
}
public function __get($n)
{
if (isset($this->data[$n])) return $this->data[$n];
throw new Exception('cant retrieve value');
}
public function setVal($name, $value)
{
$this->data[$name] = $value;
}
}
But if you want to stick with your approach then:
class test
{
private $forceFlag = false;
public function __set($name,$value)
{
if ($this->forceFlag) return $this->$name = $value;
throw new Exception('cant set value');
}
public function setVal($name, $value)
{
$this->forceFlag = true;
$this->$name = $value;
$this->forceFlag = false;
}
}
If you look at the stack trace of your exception, you'll notice the call to set __set is being triggered by this line:
$this->$name = $value;
Then in __set, it does $this->setVal($n, $v), which uses the default value of false, and thus throws the exception. To fix this, you can modify your call in __set to be:
$this->setVal($n, $v, true);
With the above code, this line:
$this->$name = $value;
...invokes:
test::__set('blah', 'test');
...because test::$blah is undefined, which in turn invokes:
test::setVal('blah', 'test', false);
A possible, yet not perfect, workaround is this:
public function setVal($name, $value, $forceSet=false)
{
if (!$forceSet && isset($value))
{
throw new Exception('cant set value');
}
$this->$name = null;
$this->$name = $value;
}
Although I'm not sure what the point of your code is.
It looks like you write much code for a functionality PHP offers out of the box:
$b = new test;
$b->blah = 'test';
print_r($b);
You don't need __set for this, nor the setVal(ue) function.
However when you want to control the access, you need to ensure that you're not binding it to members. Instead store it inside of a map as a private member:
class test
{
private $values;
public function __set($n,$v)
{
$this->setVal($n, $v);
}
public function setVal($name, $value, $forceSet=false)
{
if (!$forceSet)
{
throw new Exception('cant set value');
}
$this->values[$name] = $value;
}
}
This ensures, that a member exists that is set, so that __set is not triggered again.
After testing so many options .. the is the one that works the best for me
I chose this because
Use of Exception terminates the entire scripts or one has to catch exception anything time a value is declared
__set and __get can easily be overriding by extending class
Implementation that can be used with multiple class
What to be able to use the Object directly without having to add another getter method
Locking can cause conflict
The script would not change your existing application structure
Can be used with Singleton ..
Code :
abstract class Hashtable
{
final $hashTable = array() ;
final function __set($n,$v)
{
return false ;
}
final function __get($n)
{
return #$this->hashTable[$n] ;
}
final function _set($n, $v)
{
$this->hashTable[$n] = $v ;
}
}
class Test extends Hashtable {} ;
$b = new Test();
$b->_set("bar","foo",true);
$b->_set("hello","world",true);
//$b->setVal("very","bad"); // false
$b->bar = "fail" ;
var_dump($b,$b->bar);
Output
object(Test)[1]
public 'hashTable' =>
array
'bar' => string 'foo' (length=3)
'hello' => string 'world' (length=5)
string 'foo' (length=3)
I hope this helps
Thanks
:)
I want to write a sort of "plugin/module" system for my code, and it would make it much easier if I could "add" stuff into a class after it's been defined.
For example, something like this:
class foo {
public function a() {
return 'b';
}
}
There's the class. Now I want to add another function/variable/const to it, after it's defined.
I realize that this is probably not possible, but I need confirmation.
No, you cannot add methods to an already defined class at runtime.
But you can create similar functionality using __call/__callStatic magic methods.
Class Extendable {
private $handlers = array();
public function registerHandler($handler) {
$this->handlers[] = $handler;
}
public function __call($method, $arguments) {
foreach ($this->handlers as $handler) {
if (method_exists($handler, $method)) {
return call_user_func_array(
array($handler, $method),
$arguments
);
}
}
}
}
Class myclass extends Extendable {
public function foo() {
echo 'foo';
}
}
CLass myclass2 {
public function bar() {
echo 'bar';
}
}
$myclass = new myclass();
$myclass->registerHandler(new myclass2());
$myclass->foo(); // prints 'foo'
echo "\n";
$myclass->bar(); // prints 'bar'
echo "\n";
This solution is quite limited but maybe it will work for you
To add/change how classes behave at runtime, you should use Decorators and/or Strategies. This is the prefered OO approach over resorting to any magic approaches or monkey patching.
A Decorator wraps an instance of a class and provides the same API as that instance. Any calls are delegated to the wrapped instance and results are modified where needed.
class Decorator
{
// …
public function __construct($decoratedInstance)
{
$this->_decoratedInstace = $decoratedInstance;
}
public function someMethod()
{
// call original method
$result = $this->_decoratedInstance->someMethod();
// decorate and return
return $result * 10;
}
// …
}
For Strategy, see my more complete example at Can I include code into a PHP class?
More details and example code can be found at
http://sourcemaking.com/design_patterns/decorator
http://sourcemaking.com/design_patterns/strategy
I have a few methods for you to try. :) Have fun coding.
Method for only one class:
class main_class {
private $_MODS = array(),...;
public ...;
public function __construct(...) {
...
global $MODS_ENABLED;
$this -> $_MODS = $MODS_ENABLED;
}
...
public function __get( $var ) {
foreach ( $this->_MODS as $mod )
if ( property_exists( $mod, $var ) )
return $mod -> $var;
}
public function __call( $method, $args ) {
foreach ( $this->_MODS as $mod )
if ( method_exists( $mod, $method ) )
return call_user_method_array( $method, $mod, $args );
}
}
Method for when you want to deal with more than one class:
class modMe {
private $_MODS = array();
public function __construct__() {
global $MODS_ENABLED;
$this -> $_MODS = $MODS_ENABLED;
}
public function __get( $var ) {
foreach ( $this->_MODS as $mod )
if ( property_exists( $mod, $var ) )
return $mod -> $var;
}
public function __call( $method, $args ) {
foreach ( $this->_MODS as $mod )
if ( method_exists( $mod, $method ) )
return call_user_method_array( $method, $mod, $args );
}
}
class mainClass extends modMe {
function __construct(...){
$this -> __construct__();
}
}
Now lets try to use them:
$MODS_ENABLED = array();
$MODS_ENABLED[] = new mod_mail();
$myObj = new main_class(...);
$myObj -> mail("me#me.me","you#you.you","subject","message/body","Extra:Headers;More:Headers");
# Hey look, my mail class was just added into my main_class for later use.
Note:
I am currently using the first method (I only have one class, the mods are exceptions) in my own CMS that I have made from scratch (http://sitegen.com.au), and it works great, my reason on needing this is because I have my main_class that is getting generated after I have required all mods in ./mods-enabled/* creating functions and changing how other functions work, I will also come back here another time with a solution for two mods to both change a function without one winning as it ran first. I have split my plugins in two, mods that run on every site, and plugins that have settings for a site and may not even be enabled.
Have fun programming.
You can extend the class
class foo {
public function a() {
return 'b';
}
}
class woo extends foo {
public function newStuff() {
$var = $this->a();
echo $var;
}
}
By extending foo from the woo class the functionality in foo is usable while you can also create new methods in woo. That's the easiest way to add new functionality to a class.
You can use magic functionality of PHP to provide actions on methods that are not defined at compile time.
It is actually possible. For instance:
<?php
class Test {
function set($set, $val) {
$this->$set = $val;
}
function get($get) {
return $this->$get;
}
}
$t = new Test();
$t->set('hello', 'world');
echo $t->get('hello');
exit;
?>
If it is not enough magic for you, you can use dynamic objects. The common idea is here: https://github.com/ptrofimov/jslikeobject
I was writing a class that uses __get() and __set() to store and retrieve array elements in a master array. I had a check to make some elements ungettable, basically to re-create private properties.
I noticed that it seemed that __get intercepts all calls to class properties. This sucks for me, because I wanted to have a variable private to the outside world ( unavailable via get ), but I was trying to access it by directly referencing the master array from within the class. Of course, the master array is not in the whitelist of gettable properties :(
Is there a way I can emulate public and private properties in a php class that uses __get() and __set()?
Example:
<?
abstract class abstraction {
private $arrSettables;
private $arrGettables;
private $arrPropertyValues;
private $arrProperties;
private $blnExists = FALSE;
public function __construct( $arrPropertyValues, $arrSettables, $arrGettables ) {
$this->arrProperties = array_keys($arrPropertyValues);
$this->arrPropertyValues = $arrPropertyValues;
$this->arrSettables = $arrSettables;
$this->arrGettables = $arrGettables;
}
public function __get( $var ) {
echo "__get()ing:\n";
if ( ! in_array($var, $this->arrGettables) ) {
throw new Exception("$var is not accessible.");
}
return $this->arrPropertyValues[$var];
}
public function __set( $val, $var ) {
echo "__set()ing:\n";
if ( ! in_array($this->arrSettables, $var) ) {
throw new Exception("$var is not settable.");
}
return $this->arrPropertyValues[$var];
}
} // end class declaration
class concrete extends abstraction {
public function __construct( $arrPropertyValues, $arrSettables, $arrGettables ) {
parent::__construct( $arrPropertyValues, $arrSettables, $arrGettables );
}
public function runTest() {
echo "Accessing array directly:\n";
$this->arrPropertyValues['color'] = "red";
echo "Color is {$this->arrPropertyValues['color']}.\n";
echo "Referencing property:\n";
echo "Color is {$this->color}.\n";
$this->color = "blue";
echo "Color is {$this->color}.\n";
$rand = "a" . mt_rand(0,10000000);
$this->$rand = "Here is a random value";
echo "'$rand' is {$this->$rand}.\n";
}
}
try {
$objBlock = & new concrete( array("color"=>"green"), array("color"), array("color") );
$objBlock->runTest();
} catch ( exception $e ) {
echo "Caught Exeption $e./n/n";
}
// no terminating delimiter
$ php test.php
Accessing array directly:
__get()ing:
Caught Exeption exception 'Exception' with message 'arrPropertyValues is not accessible.' in /var/www/test.php:23
Stack trace:
#0 /var/www/test.php(50): abstraction->__get('arrPropertyValu...')
#1 /var/www//test.php(68): concrete->runTest()
#2 {main}.
Is there a way I can emulate public and private properties in a php class that uses __get() and __set()?
Not directly (if you discount debug_backtrace).
But you can have a private method getPriv that does all the work your current __get does. Then __get would only wrap this private method and check accessibility.
function __get($name) {
if (in_array($name, $this->privateProperties))
throw new Exception("The property ". __CLASS__ . "::$name is private.");
return $this->getPriv($name);
}
Inside your class, you would call getPriv, thus bypassing __get.
Make abstraction::$arrPropertyValues protected or do what Artefacto wrote (if you need additional checks), except that abstraction::getPriv() should be protected.
Rather than manually enlisting private/protected properties, you could use PHPs cumbersome reflection methods:
function __get($name) {
$reflect = new ReflectionObject($this);
$publics = $reflect->getProperties(ReflectionProperty::IS_PUBLIC);
if (in_array($name, $publics)) {
return $this->{$name};
}
}
In using PHP's DOM classes (DOMNode, DOMEElement, etc) I have noticed that they possess truly readonly properties. For example, I can read the $nodeName property of a DOMNode, but I cannot write to it (if I do PHP throws a fatal error).
How can I create readonly properties of my own in PHP?
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.
Since PHP 8.1 there are implemented native readonly properties
Documentation
You can initialize readonly property only once during the declaration of the property.
class Test {
public readonly string $prop;
public function __construct(string $prop) {
$this->prop = $prop;
}
}
--
class Test {
public function __construct(
public readonly string $prop,
) {}
}
Trying to modify the readonly propety will cause following error:
Error: Cannot modify readonly property Test::$prop
Update PHP 8.2
Since PHP 8.2 you are able to define as readonly a whole class.
readonly class Test {
public string $prop;
public function __construct(string $prop) {
$this->prop = $prop;
}
}
But private properties exposed only using __get() aren't visible to functions that enumerate an object's members - json_encode() for example.
I regularly pass PHP objects to Javascript using json_encode() as it seems to be a good way to pass complex structures with lots of data populated from a database. I have to use public properties in these objects so that this data is populated through to the Javascript that uses it, but this means that those properties have to be public (and therefore run the risk that another programmer not on the same wavelength (or probably myself after a bad night) might modify them directly). If I make them private and use __get() and __set(), then json_encode() doesn't see them.
Wouldn't it be nice to have a "readonly" accessibility keyword?
Here is a way to render all property of your class read_only from outside, inherited class have write access ;-).
class Test {
protected $foo;
protected $bar;
public function __construct($foo, $bar) {
$this->foo = $foo;
$this->bar = $bar;
}
/**
* All property accessible from outside but readonly
* if property does not exist return null
*
* #param string $name
*
* #return mixed|null
*/
public function __get ($name) {
return $this->$name ?? null;
}
/**
* __set trap, property not writeable
*
* #param string $name
* #param mixed $value
*
* #return mixed
*/
function __set ($name, $value) {
return $value;
}
}
tested in php7
I see you have already got your answer but for the ones who still are looking:
Just declare all "readonly" variables as private or protected and use the magic method __get() like this:
/**
* This is used to fetch readonly variables, you can not read the registry
* instance reference through here.
*
* #param string $var
* #return bool|string|array
*/
public function __get($var)
{
return ($var != "instance" && isset($this->$var)) ? $this->$var : false;
}
As you can see I have also protected the $this->instance variable as this method will allow users to read all declared variabled. To block several variables use an array with in_array().
For those looking for a way of exposing your private/protected properties for serialization, if you choose to use a getter method to make them readonly, here is a way of doing this (#Matt: for json as an example):
interface json_serialize {
public function json_encode( $asJson = true );
public function json_decode( $value );
}
class test implements json_serialize {
public $obj = null;
protected $num = 123;
protected $string = 'string';
protected $vars = array( 'array', 'array' );
// getter
public function __get( $name ) {
return( $this->$name );
}
// json_decode
public function json_encode( $asJson = true ) {
$result = array();
foreach( $this as $key => $value )
if( is_object( $value ) ) {
if( $value instanceof json_serialize )
$result[$key] = $value->json_encode( false );
else
trigger_error( 'Object not encoded: ' . get_class( $this ).'::'.$key, E_USER_WARNING );
} else
$result[$key] = $value;
return( $asJson ? json_encode( $result ) : $result );
}
// json_encode
public function json_decode( $value ) {
$json = json_decode( $value, true );
foreach( $json as $key => $value ) {
// recursively loop through each variable reset them
}
}
}
$test = new test();
$test->obj = new test();
echo $test->string;
echo $test->json_encode();
Class PropertyExample {
private $m_value;
public function Value() {
$args = func_get_args();
return $this->getSet($this->m_value, $args);
}
protected function _getSet(&$property, $args){
switch (sizeOf($args)){
case 0:
return $property;
case 1:
$property = $args[0];
break;
default:
$backtrace = debug_backtrace();
throw new Exception($backtrace[2]['function'] . ' accepts either 0 or 1 parameters');
}
}
}
This is how I deal with getting/setting my properties, if you want to make Value() readonly ... then you simply just have it do the following instead:
return $this->m_value;
Where as the function Value() right now would either get or set.