CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 11 of 11
  1. #1
    Join Date
    Aug 2002
    Location
    Brazil
    Posts
    730

    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.

  2. #2
    Join Date
    May 2004
    Location
    Germany
    Posts
    655

    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/

  3. #3
    Join Date
    Aug 2002
    Location
    Brazil
    Posts
    730

    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.

  4. #4
    Join Date
    May 2004
    Location
    Germany
    Posts
    655

    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/

  5. #5
    Join Date
    Aug 2002
    Location
    Brazil
    Posts
    730

    Resolved 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.

  6. #6
    Join Date
    Aug 2002
    Location
    Brazil
    Posts
    730

    Cool 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.

  7. #7
    Join Date
    Jan 2003
    Location
    7,107 Islands
    Posts
    2,487

    Re: How to add plugin functionality to a class?

    you may check also the runkit/classkit functions. there are some requirements though.
    Busy

  8. #8
    Join Date
    Aug 2002
    Location
    Brazil
    Posts
    730

    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.

  9. #9
    Join Date
    Jan 2003
    Location
    7,107 Islands
    Posts
    2,487

    Re: How to add plugin functionality to a class?

    yes bubu i have missd that part of your post. apologies
    Busy

  10. #10
    Join Date
    Aug 2002
    Location
    Brazil
    Posts
    730

    Smile Re: How to add plugin functionality to a class?

    You're welcome! Thank you for your attention.
    All consequences are eternal in some way.

  11. #11
    Join Date
    Nov 2004
    Location
    Slough, UK
    Posts
    184

    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.
    PHP || MySql || Apache || Get Firefox || OpenOffice.org || ClickOnline ||

    Did I ever say I was an expert?

    | PHP Session --> Database Handler * Custom Error Handler * Installing PHP * HTML Form Handler * PHP 5 OOP * Using XML * Ajax | VB6 Winsock - HTTP POST / GET * Winsock - HTTP File Upload

    Please mark threads resolved by going to the thread tools menu and clicking the Mark Thread Resolved button.

    Has a post really helped you? Please Rate it.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured