A word of warning! It may seem obvious, but remember, when deciding whether to use __get, __set, and __call as a way to access the data in your class (as opposed to hard-coding getters and setters), keep in mind that this will prevent any sort of autocomplete, highlighting, or documentation that your ide mite do.

Furthermore, it beyond personal preference when working with other people. Even without an ide, it can be much easier to go through and look at hardcoded member and method definitions in code, than having to sift through code and piece together the method/member names that are assembled in __get and __set.

If you still decide to use __get and __set for everything in your class, be sure to include detailed comments and documenting, so that the people you are working with (or the people who inherit the code from you at a later date) don't have to waste time interpreting your code just to be able to use it.

1 - Unsetting an object member removes it from the object completely, subsequent uses of that member will be handled by magic methods.2 - PHP will not recursively call one magic method from within itself (at least for the same $name).

This means that if an object member has been unset(), it IS possible to re-declare that object member (as public) by creating it within your object's __set() method, like this:

<?phpclass Foo{ function __set($name, $value) {// Add a new (public) member to this object. // This works because __set() will not recursively call itself.$this->$name= $value; }}

Also be mindful that if you want to break a reference involving an object member without triggering magic functionality, DO NOT unset() the object member directly. Instead use =& to bind the object member to any convenient null variable.

The PHP devs aren't going to implement true overloading because: PHP is not strictly typed by any stretch of the imagination (0, "0", null, false, and "" are the same, for example) and unlike Java and C++, you can pass as many values as you want to a function. The extras are ignored unless you fetch them using func_get_arg(int) or func_get_args(), which is often how I "overload" a function/method, and fewer than the declared number of arguments will generate an E_WARNING, which can be suppressed by putting '@' before the function call, but the function will still run as if you had passed null where a value was expected.

..is probably not what you should be doing. Always make sure that the methods you call in __call are allowed as you probably dont want all the private/protected methods to be accessed by a typo or something.

You should take care when using properties retrieved via __get() in functions that expect arguments to be passed by reference (e.g. mysqli_stmt_bind_param). The reference is NOT set to the property itself, but to the value returned by __get().Thus, binding a property retrieved via __get() to a statement will let the statement be executed always with the value the property had when calling bind_param, not with the current value it has when calling execute().E.g.:<?phperror_reporting(E_ALL);class foo { protected $bar;

If you want to be able to overload a variable from within a class and this is your code:<?phpclass myClass{ private $data; public function __set($var, $val) {$this->data[$var] = $val; } public function __get($var) {$this->data[$var] = $val; }}?>

There is a problem if you want to call these variables from within the class, as you you want to access data['data'] then you can't say $this->data as it will return the array $data. Therefore a simple solution is to name the array $_data. So in your __get and __set you will say $this->_data ... rather than $this->data. I.E:<?phpclass myClass{ private $_data; public function __set($var, $val) {$this->_data[$var] = $val; } public function __get($var) {$this->_data[$var] = $val; }}?>

Here's a useful class for logging function calls. It stores a sequence of calls and arguments which can then be applied to objects later. This can be used to script common sequences of operations, or to make "pluggable" operation sequences in header files that can be replayed on objects later.

If it is instantiated with an object to shadow, it behaves as a mediator and executes the calls on this object as they come in, passing back the values from the execution.

This is a very general implementation; it should be changed if error codes or exceptions need to be handled during the Replay process.<?phpclass MethodCallLog { private $callLog = array(); private $object;

Below, "FileManagerPrefs" is an object of class UserData which implements ArrayAccess. There's a protected array of UserData objects in the User class, which are returned from __get().<?php// This produces an error...Application::getInstance()->user->FileManagerPrefs[ 'base'] = 'uploads/jack';?>

Creates this error:Fatal error: Cannot access undefined property for object with overloaded property access in __FILE__ on line __LINE__

However, __get() and offsetGet() play deceptively well together.

<?php// This works fine!echo Application::getInstance()->user->FileManager['base'];?>

I guess it's a dereferencing issue with __get(). In my case, it makes more sense to have a middle step (user->data['FileManager']['base']), but I wanted to tip off the community before I move on.

Php 5 has a simple recursion system that stops you from using overloading within an overloading function, this means you cannot get an overloaded variable within the __get method, or within any functions/methods called by the _get method, you can however call __get manualy within itself to do the same thing.

If you need to also use the magic setter in your constructor, you may use this example:

<?phpclass person { private $name; private $addr; private $city;

function __construct($n,$a,$c) {$this->__set('name', $n); // Pushing "name" through the setter where it will be validated and sanitated.$this->addr = $a; // Adress is not validated$this->city = $c; // Neither is this...// $this->__set('city',$c); // But this is...}

Useful if you want to proxy or lazy load properties yet want to have documentation and visibility in the code and debugging compared to __get(), __isset(), __set() on non-existent inaccessible properties.

Actually you dont need __set ect imo. You could use it to set (pre-defined) protected (and in "some" cases private) properties . But who wants that? (test it by uncommenting private or protected)(pastebin because long ...) => http://pastebin.com/By4gHrt5

You can use __call and __callStatic for an very simple function based caching approach. If your method result needs to be cached based on its arguments then you only have to add cached_ infront of the name.

It may be important to note that when __set($name, $value) is called, $name gets entered into the symbol table for that call stack. This means that if a property is set within __set, it will only work if that property's name appears in the call stack (ie if it matches $name). If not, __set will be called again on the new property recursively.

It could be thought of like this: within the function __set($name, $value), $this->[property name] = [value] will recurse unless property name == $name. Within the call stack of __set, __set will never recurse on the same name twice. Once you leave __set (without actually creating the property), the call stack ends and all bets are off.

What this means:
You cannot do things like setting an (uppercase) property to lowercase within __set without expecting __set to be called twice. If you were to add an underscore to the property name, you can expect an infinite recursion loop.

Since this was getting me for a little bit, I figure I better pipe in here...

For nested calls to private/protected variables(probably functions too) what it does is call a __get() on the first object, and if you return the nested object, it then calls a __get() on the nested object because, well it is protected as well.

Using anon functions, you can allow your class methods to be declared after your class is already set. Though you cannot use a class property as a function in any way (including for properties that are objects with their own __invoke() method) without triggering a fatal error, there is a workaround using an array property to store all these anon functions...

If you got a parent class agregating(not inheriting) a number of child classes in an array, you can use the following to allow calling methods of the parent object on agregated child objects:<?phpclass child { public $holder = null;

Be extra careful when using __call(): if you typo a function call somewhere it won't trigger an undefined function error, but get passed to __call() instead, possibly causing all sorts of bizarre side effects.In versions before 5.3 without __callStatic, static calls to nonexistent functions also fall through to __call!This caused me hours of confusion, hopefully this comment will save someone else from the same.

<?php/* Here folows a little improvement of the 'strafvollzugsbeamter at gmx dot de' code, allowing each node to hold both 'parameters' and 'child nodes', and differentiate $s->A->B->C ('FOO') from $s->A (same 'FOO', but shouldn't exist) and from $s-A->B (idem). This allows the class, using the interesting suggested syntax ($root->dad->child->attribute, in which 'dad's and 'child's names are dynamically generated), to do something actually useful, like implementing a n-tree data structure (a menu, for instance). It was tested under PHP 5.2.6 / Windows. I know that must there be something better which already do this (probably in the DOM Model classes, or something like), but it was fun to develop this one, for the sake of studying the "magic" methods. Its a compressed version of the code (no comments, too short variable names, almost no identation). I had to compress it in order to add the note. If anyone cares about the full version, just email me. []s

"These methods will only be triggered when your object or inherited object doesn't contain the member or method you're trying to access."is not quite correct:they get called when the member you trying to access in not visible:

Of course, the use of this is questionable (I have never needed it myself, but then again, I only have a very minimalistic C++ & JAVA background). However, using this general principle and optionally building forth on other suggestions a 'form' of overloading is definately possible, provided you have some strict naming conventions in your functions.

It would of course become a LOT easier once PHP'd let you declare the same member several times but with different arguments, since if you combine that with the reflection class 'real' overloading comes into the grasp of a good OO programmer. Lets keep our fingers crossed!

Just to reinforce and elaborate on what DevilDude at darkmaker dot com said way down there on 22-Sep-2004 07:57.

The recursion detection feature can prove especially perilous when using __set. When PHP comes across a statement that would usually call __set but would lead to recursion, rather than firing off a warning or simply not executing the statement it will act as though there is no __set method defined at all. The default behaviour in this instance is to dynamically add the specified property to the object thus breaking the desired functionality of all further calls to __set or __get for that property.

public function validate($name){/* __get will be called on the following line but as soon as we attempt to call __set again PHP will refuse and simply add a property called $name to $this */$this->$name = trim($this->$name); }}

When overriding __get and __set, the above code can work (as expected) but it depends on your __get implementation rather than your __set. In fact, __set is never called with the above code. It appears that PHP (at least as of 5.1) uses a reference to whatever was returned by __get. To be more verbose, the above code is essentially identical to:

Yet another way of providing support for read-only properties. Any property that has
"pri_" as a prefix will NOT be returned, period, any other property will be returned
and if it was declared to be "protected" or "private" it will be read-only. (scope dependent of course)

for anyone who's thinking about traversing some variable treeby using __get() and __set(). i tried to do this and found oneproblem: you can handle couple of __get() in a row by returningan object which can handle consequential __get(), but you can'thandle __get() and __set() that way.i.e. if you want to:<?phpprint($obj->val1->val2->val3); // three __get() calls?> - this will work,but if you want to:<?php $obj->val1->val2 = $val; // one __get() and one __set() call?> - this will fail with message:"Fatal error: Cannot access undefined property for object with overloaded property access"however if you don't mix __get() and __set() in one expression,it will work:<?php $obj->val1 = $val; // only one __set() call$val2 = $obj->val1->val2; // two __get() calls$val2->val3 = $val; // one __set() call?>

as you can see you can split __get() and __set() parts ofexpression into two expressions to make it work.

echo "The name of the form that '" . $objWE1->GetWebFormElementName() . "' is in is '" . $objWE1->GetWebFormName() . "'<br />";echo "The name of the document that '" . $objWE2->GetWebFormElementName() . "' is in is '" . $objWE2->GetWebDocumentName(). "'<br />";echo "The name of the frame that '" . $objWE3->GetWebFormElementName() . "' is in is '" . $objWE3->GetWebFrameName(). "'<br />";echo "The name of the page container that '" . $objWE4->GetWebFormElementName() . "' is in is '" .$objWE4->GetWebPageContainerName(). "'<br />";?>

Results in.

The name of the form that 'Element 1' is in is 'Form 1'The name of the document that 'Element 2' is in is 'Doc 1'The name of the frame that 'Element 3' is in is 'Frame 2'The name of the page container that 'Element 4' is in is 'The outer web page container.'

By using the abstract BubbleMethod class as the starting point for further classes that are contained inside others (i.e. elements on a form are contained in forms, which are contained in documents which are contained in frames which are contained in a super wonder global container), you can find properties of owner without knowing their direct name.

I've tried a couple of different ways of doing this, but this seems to be the fastest (although still around 2 times slower than using ugly old school getter- and setter-methods).Functions like property_exists() are unnecessary and only makes thing even slower (my initial attempt at using __set and __get was up to 9 times slower than traditional getter/setter methods).

Could probably still be improved/changed in different ways depending on context.

Whats happening, is PHP is acquiring a reference to the object, triggering __get; Then applying the changes to the object via the reference.

Which is the correct behaviour; objects being special creatures, with an aversion to being cloned...

Unfortunately this will never invoke the __set handler, even though it is modifying a property within 'foo', which is slightly annoying if you wanted to keep track of changes to an objects overloaded properties.

// The deal here is to use following code:
WantStaticCall::register('logger');
WantStaticCall::doSomething('logger', $argumentList);

// and we will make objDriver to call his doSomething function with arguments
// $argumentList. This is not common pattern but very usefull in some cases.
// The problem here is that __call() cannot be static, Is there a way to work it around
?>

# IMPORTANT: you can keep some things private - or treat # some vars differently by giving them their own getter method # See how this function lies about Person's weight.function getWeight() { return intval($this->weight * .8); } }