Monkey Loader is a mechanism to attempt fake class re-loading in PHP.
The idea spawned from a need to re-load plug-ins in my IRC Bot, Cirno
(https://github.com/ElvenSpellmaker/IRC-Bot).
After instantiating an instance of the MonkeyLoader class, objects may be
generated by calling one of the various get
methods available.
PHP >= 5.5
Monkey Patching is a common term for being able to change a programme's code while it is running, such as class re-loading. Monkey Loader fakes PHP Class re-loading.
Also, the method I use to fake this is cheeky and monkeys are cheeky. ;-)
Incomplete PHP files are the mechanism for Monkey Loader. These files are nearly valid PHP classes without the class wrapper or beginning PHP tag.
They start with a meta tag which houses any extends
or implements
information for the class.
Then the class is inside a class tag.
An example is below:
src/Foo/Foo.php
<?php
namespace Foo;
// Foo extends Foo\Bar and implements Baz.
class Foo extends Bar implements Baz
{
protected $foo = true;
public function sayFoo() { echo 'Foo!'; }
}
src/Foo/Foo.iphp
meta:
extends Bar implements Baz
class:
protected $foo = true;
public function sayFoo() { echo 'Foo!'; }
Monkey Loader uses an eval()
call to scope your classes into place. By using
the provided methods you can ask for instances of an object to be loaded and if
the file changes, re-load the class (by defining a new class) and return that
new instance instead. It does this by appending class information around
Incomplete PHP Files *.iphp
and incrementing the chosen class name e.g. Foo
to Foo1
.
Each method also has a version which will not attempt to load a new class which
all have cached in their name getCached*()
.
Monkey Loader supports:
- Loading classes
- Re-loading Classes
- Singletons (User maintained however)
- Namespaces
- Extends and Implements
get()
- Gets an instance of the passed class, this will attempt to find a new
class.
getCached()
- Gets an instance of the passed class without new finding.
getSingleton()
- Gets a singleton of the class checking for new classes.
getCachedSingleton()
- Gets a singleton of the class without checking for
updates.
isSameClass()
- Compares two class strings or two objects (or a mix of the
two) for the same class loaded through Monkey Loader.
There are a few caveats with using this sort of method:
- The objects returned will not be the same class between re-loads.
Attempting to use any equality (
==
/===
) on differing versions of objects will fail. This also applies to class comparisons too, which should be done withisSameClass()
. - Typehints will fail after the first instance, due to how this library works.
A method with the signature
public function foo(Foo $foo)
would work with the firstFoo
object, but the next would beFoo1
and would fail the type hint. - Memory usage will increase with every class re-load. This is due to the fact that the original class is still in memory.
- Beware of the Singleton methods! Because of the way Monkey Loader works there is no way to guarantee that all old references to the old singleton are wiped out! This means it's up to you to maintain references and keep singletons singleton.
- Due to how this works, if a class isn't available your application will terminate, e.g.:
class Foo1 {}
$ml = new MonkeyLoader;
$foo = $ml->get( 'Foo' );
// Change Foo file.
// This will crash as Foo1 is already taken.
$foo = $ml->get( 'Foo' );
- Work out some kind of way to transfer data from one instance to another (in the case of singletons especially as they should give the appearance of the "same" object throughout revisions.)
- Using the above implement an
==
style method that ignores Class Type but attempts to use the getData methods to work out if objects are 'equal'.