|
-
February 7th, 2007, 01:14 AM
#1
How to add plugin functionality to a class?
I want to add plug-in functionality to a class. That is, I want the class to have a function called load_plugin($file) that includes the $file so that all code inside $file is now functions of the class.
Sounds weird? Let me explain. I have 2 files:
sample-plugin.php
PHP Code:
<?php function new_class_function() { $this->name = 'Class Name 2'; }
new_class_function(); ?>
myclass.php
PHP Code:
<?php class cms { $var name;
function cms() { $this->name = 'class name'; }
function load_plugin($file) { include $file; } }
$cms = new cms(); echo $cms->name; $cms->load_plugin('sample-plugin.php'); echo '<br>'.$cms->name; ?>
However, this does not work as PHP says that $this->name does not exists inside new_class_function() (quite obvious if you consider the scope of the function inside the class)
How can I do that? I know runkit and classkit can do this but those are modules not bundled with PHP.
Any questions?
All consequences are eternal in some way.
-
February 7th, 2007, 01:58 AM
#2
Re: How to add plugin functionality to a class?
hi,
have look at the overloadind of php.
You can define a "magic" __call function, with than gets called in case you call a member function which does not exist.
(How to use __call exactly depends on your php version)
Within these function you could then execute code.
Well, to inject a variable, you could also use the magic __set and __get functions but you can also simply do somehting like $this->bla = "bla";
You just have to change your include to
Code:
$this->name = 'Class Name 2';
no function... as this opens a new scope and $this is not known there.
Well, or.. you use the traditional approach of extending classes and instanciate the class you want...
hope i could point the direction
there are 10 kinds of people. those who understand binary and those who don't...
rate a post if you find it usefull, thx
check out my Firefox/Mozilla Extension: http://urlparams.blogwart.com/
-
February 7th, 2007, 02:29 AM
#3
Re: [RESOLVED] How to add plugin functionality to a class?
Very helpfull. I'll take a look into those magic methods.
But for now I can point two things wich are pending:
- i need functions and not just variable modifiers because now plugins have their own functions wich should be incorporated to the class.
- i cannot extend classes from the main cms class becasue cms class loads alot of things automatically such as logged user and his permission from database. instantiating the base class more than one will cause duplicate data and code excution without need.
if this can't be done i guess i'll have to change the cms paradigm out of singleton.
I'll try to figure if those magic methods can somehow inject new functionality into the class with includes().
All consequences are eternal in some way.
-
February 7th, 2007, 02:43 AM
#4
Re: [RESOLVED] How to add plugin functionality to a class?
well, with the magics you can call functions which do not actually exists in the class instance.
maybe you can register function names in loadPlugin and in the magic __call funcitons just call these registered functions and pass $this as function parameter.
there are 10 kinds of people. those who understand binary and those who don't...
rate a post if you find it usefull, thx
check out my Firefox/Mozilla Extension: http://urlparams.blogwart.com/
-
February 7th, 2007, 03:09 AM
#5
Re: [RESOLVED] How to add plugin functionality to a class?
Your solution seems to work well. But unfortunately i will have to add a new parameter to every function to be plugged into the class. That will cause more overhead then my current solution.
My current solution is:
index.php
PHP Code:
<?php #instantiate the cms class $cms = new cms();
# $cms->get_module() does: # checks if there is a module passed from url. uses default if none specified # checks if the module passed exists # validate passed module name against hackers if ($module = $cms->get_module(@$_GET['module'])) require_once $module; ?>
samplemodule.php
PHP Code:
if ($_GET['op'] == 'say_hi') say_hi_func();
function say_hi_func() { global $cms; $cms->tpl_append('BODY', 'Hello!'); }
As you can see modules are coded to use the instantiated class and not as if they where part of the class. To access the cms class, modules currently do $cms->func() or $cms->var.
Current way it works it's ok. But if I managed to inject the modules inside the class without overhead it would be cool.
You agree with me that using your suggestion i will be trading six for a half/dozen?
I will stop doing it like this:
PHP Code:
function say_hi_func() { global $cms; $cms->tpl_append('BODY', 'Hello!'); }
And start doing it like this:
PHP Code:
function say_hi_func($cms) { $cms->tpl_append('BODY', 'Hello!'); }
Still, i'll convert all modules into your suggestion because is more on the oop side than my current solution.
I still wait for a better suggestion. Thank you bigBA.
Last edited by bubu; February 7th, 2007 at 03:13 AM.
All consequences are eternal in some way.
-
February 7th, 2007, 03:28 AM
#6
Re: [RESOLVED] How to add plugin functionality to a class?
I don't know if you already knew this. But it's a dark side of PHP:
index.php
PHP Code:
class CMS { var $frase; function CMS() { $this->frase = 'God is so mighty!';
require_once 'module.php'; } } $cms = new CMS(); echo $cms->frase;
module.php
PHP Code:
function hehe() { $this->frase = 'NOZZZZ'; }
#works because code just stays in scope where it was included $this->frase = 'YESSSZ';
#doesn't work becasue functions in include files go to global scope $this->hehe();
#doesn't work because load_plugin() function doesn't know about $cms; $cms->hehe();
Like it says in PHP manual:
When a file is included, the code it contains inherits the variable scope of the line on which the include occurs. Any variables available at that line in the calling file will be available within the called file, from that point forward. However, all functions and classes defined in the included file have the global scope.
Reading this I can't imagine how can my dream become true. Functions will always go global scope no matter where they where included.
BigBA do you think your solution is a little difficult for an average webdeveloper to understand when extending my CMS? (because we are all genius here)
All consequences are eternal in some way.
-
February 8th, 2007, 12:56 AM
#7
Re: How to add plugin functionality to a class?
you may check also the runkit/classkit functions. there are some requirements though.
Busy 
-
February 8th, 2007, 02:00 AM
#8
Re: How to add plugin functionality to a class?
Thank you, but as I said in first post, i can't rely on them to code an Open Source CMS just because they aren't bundled with PHP. =)
All consequences are eternal in some way.
-
February 9th, 2007, 06:37 AM
#9
Re: How to add plugin functionality to a class?
yes bubu i have missd that part of your post. apologies
Busy 
-
February 9th, 2007, 11:57 AM
#10
Re: How to add plugin functionality to a class?
You're welcome! Thank you for your attention.
All consequences are eternal in some way.
-
February 11th, 2007, 01:35 PM
#11
Re: How to add plugin functionality to a class?
This is almost identical to a problem I needed to solve a few months back. Here is an overview of what I needed and how I solved it.
I run a site for a the UK division my company. The site allows customers to check orders and the details of the orders. Soon after developing the initial version, it became apparent that each customers requirements differed significantly. The choices I had were to either hack the code or build more flexibility into the system - I chose the later option and after about a month of pondering the best way to do it, I chose the following method.
- I have a controller Module class. This is basically the module loader responsible for loading any plugin code and executing the module.
- When loaded (instantiated) the Module class loads and instance of another object called a DynamicModule. This class contains all the core actions the module will need to perform such as executing queries and outputting templates.
On its own the DynamicModule would be kind of redundant. However, before creating an instance of the DynamicModule class, the Module class checks for a file with the same name as the current module. If it exists, it includes this code (using includeinstead of reuqire is important if you don't want buggy plugin code to kill the script).
When it comes to creating an instance of the DynamicModule, the Module class then checks for the existence of a class with the same name as the module AND that this class is a sub class (inherits /extends) the DynamicModule class. This means that any function within the DynamicModule class can be overridden provided its not private or final and new functions can be added or executed.
- The real beauty of this is that you can implement trigger functions. These are functions that are executed as a result of an event that occurs during the execution of the module. None of these functions need exist in the DynamicModule class because you can check if they exist at run time and execute them if they do.
One of the things I have done is use trigger functions while executing querys:
OnBeforeExecute_queryname - executed before the SQL is sent to the database allowing extra place holders to be added or even other queries to be executed before.
OnExecute_queryname - executed for each row returned and passed the data, allowing it to be manipulated or processed if required.
This makes the whole set-up immensely more flexible and because it uses inheritance there is no limit to the number of times you can override a function. I have extended this system further to look for a file specific (looking for a class name that ends in the user ID) to the current user, in effect allowing me to make individual changes to that affect a single customer only.
I have provided a short example of how it is done below:
PHP Code:
class Module
{
private $dynamicModule;
public function __construct($moduleName)
{
if (file_exists("plugins/$moduleName.php")) {
include "plugins/$moduleName.php";
}
if(class_exists($moduleName) && is_subclass_of($moduleName,'DynamicModule') {
$this->dynamicModule = new $moduleName($this);
} else {
$this->dynamicModule = new DynamicModule($this;
}
}
public function execute()
{
$this->dynamicModule->execute();
}
}
class DynamicModule
{
private $module;
public final function __construct(Module $module)
{
$this->module = $module;
}
public final function execute()
{
// pass arguments as an array, you could if you wanted stop execution
// if the function returns a non true value
$this->executeTriggerFunction('onBeforeExecute');
/* other execution code here */
$this->executeTriggerFunction('onAfterExecute');
}
private executeTriggerFunction($functionName, $args = array())
{
if (method_exists($this, $functionName)) {
reutrn call_user_func_array(array($this, $functionName), $args);
} else {
return true;
}
}
}
And a plugin file will look something like this:
PHP Code:
/* plugins/MyModule.php */
class MyModule extends DynamicModule
{
/* private class members - anything you like */
private $snake;
function onBeforeExecute()
{
/* plugin code here */
}
}
Obviously, the potential for flexibility here is immense. You could add functions that allow the writer to add and remove session variables private to the current plugin, have query triggers (like explained above). Use a specially designed exception class to halt execution of a module from within a plugin and even allow the plugin to override variables that define the location of stylesheets, client side scripts and HTML templates.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|