Gerben Jacobs
Gerben Jacobs

Reputation: 4583

Overriding core classes

No idea if it's possible what I want, but I'm working on an application that requires custom classes to override the core functionality, if these files exist.

So as an example, this is my current file structure (simplified, without 'customer_slug')

Now I want to check if "custom/User.php" exists and accordingly include and use this. It should extend the core (abstract) User class.

My "entry" script looks like this at the moment:

<?php

function __autoload($class_name) {
    $dispatch = Dispatcher::getInstance();
    $dispatch->get($class_name);
}

class Dispatcher {

    private static $instance;
    private static $customer_slug = 'sony';

    private function __clone() {
        // Empty magic function to prevent cloning
    }

    private function __construct() {
        // Empty magic function to prevent initialization
    }

    public static function getInstance() 
    {
        if (!isset(self::$instance)) {
            $class = __CLASS__;
            self::$instance = new $class;
        }

        return self::$instance;
    }   

    public static function get($class) {
        // Autoload class
        $basepath = $class.'.php';

        // Include bas class
        include('core/'.$basepath);

        // Do we have custom functionality
        if (file_exists('custom/'.self::$customer_slug.'/'.$basepath)) {
            include('custom/'.self::$customer_slug.'/'.$basepath);
        } 
    }
}

$User = new User;

print_r($User);

?>

I've tried fiddling with Namespaces, but can't really seem to get it working. I would like to keep saying "$user = new User;". No idea how else I'd call the class, perhaps $user = new $custom_or_code_classname

So I'm open to other approaches as well. Maybe a hook system?

Upvotes: 2

Views: 899

Answers (1)

MikeG
MikeG

Reputation: 21

We implemented a solution to this using the __autoload(). Basically you have 2 variables, one for "app" and one for "client". Then you structure your classes in directories that match. e.g.

classes/app1/User.php
classes/app2/User.php
classes/app1/client1/User.php

etc

Then in the autoload fxn you build an array of possible paths. assuming app1, client1, array would be:

$paths = array('classes/app1/client1/User.php', 'classes/app1/User.php', 'classes/User.php');

Then iterate through looking for file_exists() and calling require_once().

All of the classes themselves should be named based on where they live:

class User__client1__app1 extends User__client1
class User__client1 extends User__base
class User__base

So the tricky part here is effectively aliasing the proper one to the root name (User).

In the autoloader, after you've found the proper class, do:

eval("class User extends $found_class { }");

Upvotes: 2

Related Questions