Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP class and method overriding - implement callbacks

Tags:

php

I'm currently working on a project where the core system is distributed out to many different clients - and then should the client request changes, we have to make them individually on each system which means that eventually the core code varies from client to client, and keeping it up to date and copying new features across the system is difficult.

I have proposed we move to (what I'm calling) an 'override model' which has an outside skeleton structure of the code. Somewhat like:

|- controllers
|- models
|- views
|- core
    |- controllers
         |- Controller1.php
    |- models
    |- views

If you then wanted to make changes to Controller1.php, you would copy it into the outside structure and make changes - an autoloader would then load the appropriate files if they exist by checking the Skeleton structure for them first, i.e.

Loader::controller('Controller1');

However I wondered if it is possible to go a bit further than that - its all well and good overriding the Controller if changes are needed, but then any future core additions or fixes might not get added in. So I thought you could possibly create a copy of the file and override just the singular method calls. An semi-example of what I mean is as follows:

class Override {

public function __call($method, $args) {
    return call_user_func_array(array('Something', $method), $args); 
}

public static function __callStatic($method, $args){
    return call_user_func_array(array('Something', $method), $args);
    }

}

// Core class
class Something {

    static function doTest() {
        echo "Class something <br/>";
    }

    static function doOtherTest() {
        echo "That works <br/>";
        self::doTest();
    }

}


// Overriding class - named differently for ease of example and reasons explained later
class SomethingElse extends Override {

    private static function doTest() {
        echo "Success <br/>";
    }

 }

 // Actual function calling
 SomethingElse::doTest();
 SomethingElse::doOtherTest();

The general idea being that if the method doesn't exist in the originating class, then action it from the 'parent' class (which is hardcoded here). However I have two issues with this method:

  • I think I will run into trouble when the classes have the same names
  • If I am attempting to override a method that the parent class subsequently calls, it will use it's own version of the method as opposed to the one I am attempting to override
    • Although the 'simple' solution is to say you should override any methods that are in conjunction, but more might be added at a later date.

Currently I am trying to just do the initial solution of full class overriding using the loader, which works and is less complex.

However I wondered if any of the great minds on StackOverflow might know of any answer or set-up that might help address the issues with the method overriding idea - please bear in mind I'm working with an existing system set up, although the skeleton structure idea is what I am trying to implement to bring some form of 'control' over what is changed. Ideally, nothing in the core would change (at least not by much) when someone wants to override a method or similar.

like image 795
Dan Avatar asked Dec 20 '12 09:12

Dan


2 Answers

Well we've just solved it. Traits it is!

But seriously by converting the versioned code to traits and then calling them in the non versioned files in the above structure. This then negates the need for a loader class and other clash prevention layers and allows the core code to be updated, tested and committed without affecting custom code per client.

like image 57
Bokers Avatar answered Oct 15 '22 18:10

Bokers


well the strict OO Kind of Solution would surely be to spread your controller as abstract interfaces that could be implementet by several different real world approaches and then brought together by the composition over inheritace principle.

As i understand you've got existing code here that you intend to override or extend. If your PHP-Version allows you to use Traits, this might help you too:

PHP 5.4: why can classes override trait methods with a different signature?

like image 28
wegus Avatar answered Oct 15 '22 17:10

wegus