A few PHP design basics for people who have forgotten them.
== Lazy load everything ==
The hottest hotspot is always initialisation. Initialisation runs on every single request. Every extension adds its own initialisation overhead, and there may be many extensions. Therefore, it is critical that initialisation is heavily optimised.
So if you're writing an extension, don't do anything at initialisation time (either file scope or $wgExtensionFunctions) except setting globals to literals.
Don't initialise data that you think you might need. Wait until you're asked for it and load it then. Cache it if necessary. Think in terms of a pull model, not a push model.
Loading large amounts of code is slow and memory hungry, especially on installations without an opcode cache. So lazy-load your code, by putting everything into autoloaded classes. Use static member functions for hooks.
== Global variables are evil ==
In MediaWiki, global variables should be used for configuration, and nothing else. There are some legacy object globals defined in old code, and you might have to use them from time to time, but don't go adding more of them. And don't reference any global variable unless you have to.
If you do need to use a legacy global variable such as $wgUser, just put the global statement where it's needed. Don't pull the object out of the global namespace and pass it from function to function unless there's a concrete need for that versatility.
Passing global objects from function to function is not a reasonable substitute for direct reference to a global variable. When the revolution comes, you will know it.
== Objects are hashtables ==
Member variables can be added and removed dynamically. It is your fundamental right as a PHP programmer to do this, nobody will ever take it away from you.
You can test for existence with isset($this->var), delete a variable with unset($this->var), reference variables with dynamic names using $this->$name, and even convert to and from the array type, (array)$obj.
It is nice from a self-documentation standpoint to put var declarations at the top of your classes. But understand that a var declaration takes up time and space when the object is initialised. If you leave it out, that overhead can be deferred, and maybe skipped altogether.
But the most important part of this paradigm is that extensions can create custom member variables in core objects.
Say if you're writing a hook and you need to cache some data. You could put it in a global variable or static member variable, but the trouble is, unless you're very careful, you lose versatility in the hook caller.
Most hooks have an object as their first parameter. This object is a great place to put your extension data relating to that object. When the caller is done with the object, it will go out of scope and your data will be deleted. And your code will implicitly be versatile enough to support any number of objects present in the system at any given time.
Prefix your custom member variables with the name of your extension, to avoid conflicts.