Welcome!

Join our community of MMO enthusiasts and game developers! By registering, you'll gain access to discussions on the latest developments in MMO server files and collaborate with like-minded individuals. Join us today and unlock the potential of MMO server development!

Join Today!

Optimal plugin system?

Experienced Elementalist
Joined
Dec 17, 2008
Messages
209
Reaction score
31
I have always been in love with the idea of other people being able to extend my work without having to actually edit anything, which is why I've spent a lot of time trying to conjure up a plugin system that would fit my needs very nicely. Here's what I've come up with and I was wondering if some of the more advanced PHP coders could take a look, maybe make some improvements.

class.plugins.php:
PHP:
<?php

class plugins {

	private $plugins = array();
	
	public function add($name, $path) {
		include $path;
		$this->plugins[$name] = new $name();
	}

	public function hook($hook, $params = array()) {
	
		$hook = "hook_" . $hook;
		
		foreach($this->plugins as $plugin) {
		
			if(method_exists($plugin, $hook)) $plugin->$hook($params);
		
		}
		
		return true;
	
	}

}

?>

plugin.testplugin.php:
PHP:
<?php

class testplugin {

	public function hook_plugin_loaded($params = array()) {
	
		print("Test plugin loaded!");
	
	}

}

?>

test.php:
PHP:
<?php

include "class.plugins.php";

$plugins = new plugins();

foreach(glob("plugin.*.php") as $path) {

	$name = substr(substr($path, 7), 0, -4);
	
	$plugins->add($name, $path);

}

$plugins->hook("plugin_loaded");

?>

(Yes, I do realize the error in using print inside a class but this was merely for demonstration.)
 
Last edited:
Joined
May 23, 2008
Messages
1,071
Reaction score
574
Nicely done. What you've done here is create something close to an implementation of the very popular . You have the ability to create "signals" via your add method, and the ability to observe on said signals via your hook method. All you need now is a way to send messages to your observers (i.e. triggering a "signal"), as opposed to simply having your observer execute largely arbitrary code once, as you currently do. This will make your system a lot more powerful and flexible.


jQuery, a popular Javascript library, actually implores the observer pattern constantly.

Code:
$('#my-element').click(function() {
    // Do stuff...
};
Can you tell what's the observer, what it's observing on, and how it is triggered? jQuery abstracts a lot of this away, but we can see some things right up front.

The $('#my-element') object is waiting for click to be triggered. This click event is actually being listened for in the background - your browser makes it easy, and jQuery abstracts it just a tad. To listen for a click event with vanilla javascript (no libraries), you would do something like
Code:
var myElement = document.getElementById('my-element');
myElement.addEventListener('click', function() {
    // Do stuff...
}, false);



I created an abstracted implementation of the observer patter in PHP a while back, too. it's fun! Although my solution was complex, it got the job done for my needs quite well. There's a lot of things I'd improve about it if I were still working on the library.

Signals are created using SignalManager->registerSignal. They can then be listened on by events. Just attach an event to a signal using SignalManager->attachEvent. The event can be bound to any scope (thanks PHP 5.4), and run arbitrary code. When you want to trigger the events listening for a certain signal, you would just run SignalManager->triggerSignal.

Overall, good looking stuff. Consider reading up on the observer pattern, I think you'll like it.
 
Experienced Elementalist
Joined
Dec 17, 2008
Messages
209
Reaction score
31
Nicely done. What you've done here is create something close to an implementation of the very popular . You have the ability to create "signals" via your add method, and the ability to observe on said signals via your hook method. All you need now is a way to send messages to your observers (i.e. triggering a "signal"), as opposed to simply having your observer execute largely arbitrary code once, as you currently do. This will make your system a lot more powerful and flexible.


jQuery, a popular Javascript library, actually implores the observer pattern constantly.

Code:
$('#my-element').click(function() {
    // Do stuff...
};
Can you tell what's the observer, what it's observing on, and how it is triggered? jQuery abstracts a lot of this away, but we can see some things right up front.

The $('#my-element') object is waiting for click to be triggered. This click event is actually being listened for in the background - your browser makes it easy, and jQuery abstracts it just a tad. To listen for a click event with vanilla javascript (no libraries), you would do something like
Code:
var myElement = document.getElementById('my-element');
myElement.addEventListener('click', function() {
    // Do stuff...
}, false);



I created an abstracted implementation of the observer patter in PHP a while back, too. it's fun! Although my solution was complex, it got the job done for my needs quite well. There's a lot of things I'd improve about it if I were still working on the library.

Signals are created using SignalManager->registerSignal. They can then be listened on by events. Just attach an event to a signal using SignalManager->attachEvent. The event can be bound to any scope (thanks PHP 5.4), and run arbitrary code. When you want to trigger the events listening for a certain signal, you would just run SignalManager->triggerSignal.

Overall, good looking stuff. Consider reading up on the observer pattern, I think you'll like it.

I really, really like your code.
It looks good, it isn't too advanced yet still fills its purpose and I like that.
I was looking for something like this and I am gonna read up on the observer pattern. Thanks dude.
 
Experienced Elementalist
Joined
Dec 17, 2008
Messages
209
Reaction score
31
If you somehow manage to add it as override function, would be nicer.
For example: override OnUserLogin()...

But I dont know if there is an suitable override system in PHP.

Would that allow multiple plugins though?
 
Joined
Feb 22, 2012
Messages
2,103
Reaction score
1,271
Would that allow multiple plugins though?

Yes. I don't know if multiple OnUserLogin plugins, though you can code it.
You would have to code a little bit for making the plugin really compatible with your system.

example: At User Logins -> onUserLogin(), and since it is overwritten, it will use the Plugin one (if you code it).
Also, you could create an UserController system for OnUserLoadPage, idk ( onUserLoadPage($pageUrl) ).

Good luck!
 
Experienced Elementalist
Joined
Dec 17, 2008
Messages
209
Reaction score
31
Yes. I don't know if multiple OnUserLogin plugins, though you can code it.
You would have to code a little bit for making the plugin really compatible with your system.

example: At User Logins -> onUserLogin(), and since it is overwritten, it will use the Plugin one (if you code it).
Also, you could create an UserController system for OnUserLoadPage, idk ( onUserLoadPage($pageUrl) ).

Good luck!

I don't think you get what I'm saying so let me rephrase it, let's say you have multiple plugins who all overwrite onUserLogin(). Every time a plugin is loaded, it'll overwrite the onUserLogin() with that specific plugins code and therefor erasing the previously loaded plugins code, so you'd end up with only the last loaded plugin having its code active. Or am I wrong here?
 
Junior Spellweaver
Joined
Oct 27, 2008
Messages
165
Reaction score
89
You can make something similar to vQmod, the functionality is simple, it uses xml files as plugins
- First it makes a copy of the Original files into a cache directory
- Then applies the modifications to those files
- The only thing you need in the code is to intercept these methods(to change the path with the path from your plugin manager):
include()
include_once()
require()
require_once()


The only problem with this is if you have 2 plugins, modifying the same thing would result a error.
 
Last edited:
Experienced Elementalist
Joined
Dec 17, 2008
Messages
209
Reaction score
31
You can make something similar to vQmod, the functionality is simple, it uses xml files as plugins
- First it makes a copy of the Original files into a cache directory
- Then applies the modifications to those files
- The only thing you need in the code is to intercept these methods(to change the path with the path from your plugin manager):
include()
include_once()
require()
require_once()


The only problem with this is if you have 2 plugins, modifying the same thing would result a error.

I was thinking of using xml files at first, with the plugin files looking like this:
Code:
<plugin name="testplugin">

	<hook name="plugin_loaded">
		<!-- php code here -->
	</hook>
	
</plugin>
and then using eval() to run the code within each hook, but using eval() like that is ugly and bad so I chose another method.

However, your suggested method would cause problems with having 2 plugins modifying the same thing which kinda ruins everything for me. I want users to be able to have 2 or more plugins do the same thing without causing any trouble.
 
Joined
Feb 22, 2012
Messages
2,103
Reaction score
1,271
I don't think you get what I'm saying so let me rephrase it, let's say you have multiple plugins who all overwrite onUserLogin(). Every time a plugin is loaded, it'll overwrite the onUserLogin() with that specific plugins code and therefor erasing the previously loaded plugins code, so you'd end up with only the last loaded plugin having its code active. Or am I wrong here?

That is what I meant, you only would be able to use one overwrite for each function. But well, if you work a little hard you would be able to create multiple. Not necessarily with overwrite.
 
Back
Top