PHP – Load 2 classes with the same name in different files

When you are dealing with code that is used in different sites or a site with different languages at least once you will find yourself in this situation: the need of using the same class coming from 2 different files. For example, using a configuration file from different sites in the same script.

If you tried, or even if you don’t, you will know that this results in a fatal error. The solution is usually doing a wrapper to execute the the script for the different situations you need, this is a good solution but the downside is the performance when you need to launch the script with a exec or passthru (because of the process fork).

Looking for a solution I found the runkit PHP extension that allows you, among other things, to load a different class with the same name overwriting the current one. This is done with the runkit_import function and passing the path of the class file as a parameter.

The bad thing is that this PECL library is not maintained since 2006 and you know what that means… in this case the library doesn’t work in PHP 5.2+ versions. But then… someone at the office sent me a link of a github project that continues this library and made it work with PHP 5.2 and 5.3.

You will only need to download the last version from github and compile the code with these simple commads:

phpize
./configure
make
make install

When you have that you will have a runkit.so file in the dynamic modules folder of PHP, so now you only need to add it to php.ini or use the dl function to dynamically load the extension.

in php.ini

extension=runkit.so

Now you can use the following code to prove that all I’m saying is right:

a.php

class A 
{
    function overloading()
    {
        echo 'I am calling from A class' ;
    }
}

b.php

class A 
{
    function overloading()
    {
        echo 'I am calling from A class from file b.php' ;
    }
}

runkit_test.php

class A
{
    function overloading ()
    {
        echo 'Calling for the same script' ;
    }
}

$a = new A() ;
$a->overloading() ;
echo "n";
// no need for so many flags but now you can see the possibilities
if(runkit_import('/full/path/to/a.php', RUNKIT_IMPORT_CLASS_METHODS | RUNKIT_IMPORT_OVERRIDE | RUNKIT_IMPORT_CLASSES | RUNKIT_IMPORT_CLASS_PROPS | RUNKIT_IMPORT_CLASS_STATIC_PROPS)) {
    $a1 = new A();
    $a1->overloading() ;
}
echo "n";
if(runkit_import('/full/path/to/b.php', RUNKIT_IMPORT_CLASS_METHODS | RUNKIT_IMPORT_OVERRIDE | RUNKIT_IMPORT_CLASSES | RUNKIT_IMPORT_CLASS_PROPS | RUNKIT_IMPORT_CLASS_STATIC_PROPS)) {
    $b = new A();
    $b->overloading() ;
}

Will result in

Calling for the same script
I am calling from A class
I am calling from A class from b.php

And that should do it 😉

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *