1
votes

I have an old library I need in my project that doesn't utilize PSR-0/4 or any namespacing at all. It has loads of PHP files with different classes. Let's say I add this library to my project via 'classmap' autoloading (as Composer documentation suggests):

"autoload": {
    "classmap": [
        "libraries/some-lib"
    ]
}

The problem is this library doesn't use inheritance/polymorphism - it has base classes with the same names and same methods (but different implementations of those methods) in different PHP files.

libraries/some-lib/Foo.php:

class Foo
{
    public function bar()
    {
        ...
    }
}

libraries/some-lib/Foo-alternate.php:

class Foo
{
    public function bar()
    {
        ...
    }
}

So when composer is generating it's classmap Ambiguous class resolution warnings are generated for them and only one version of Foo will be available to me in my project's code via \Foo because of name collisions.

My question is what is the way to go about this problem here without modifying library code? Is there any options Composer provides for situations like this so that I can import both versions of Foo class into composer's classmap and distinguish between the two in my project as a result?

1
Don't they have a namespace of their own? - nice_dev
they dont " that doesn't utilize PSR-0/4 or any namespacing at all." - noid
This is WHY namespaces were created, to solve your problem. - delboy1978uk
i thought of something along the lines of "for each File in this directory (recursive) add the following line after the <?php tag:" and the computed value would be something like "take the file path, cut off the part before your library directory and then create a Namespace from the Rest". This would result in something like this: a file at /var/ww/webroot/vendor/mylib/src/client/mysql/house.php would get a namesapce like Mylib\Client\Mysql. - Tobias F.
@TobiasF. but namespacing files will modify library code and that is something I am trying to avoid (updating library would require generating those namespaces once again and that is not something very obvious for someone other than me who might be supporting this project in the future). It's a possible solution, but it has it's downsides too as you can see. - d3jn

1 Answers

2
votes

PHP does not allow two classes to have the same name, so even if you will find workaround for this (like manually loading class from specified file depending on context) this will be more like brittle hack than real solution and it will fail when you try to load these two classes in the same request.

Although you want to avoid modifying library code, this is actually the simplest and most reliable solution. It should be easy to make these changes and I doubt that library which still not uses PSR-0/4 is actively developed, so maintenance of fork should not require any additional effort.


Is there any options Composer provides for situations like this so that I can import both versions of Foo class into composer's classmap and distinguish between the two in my project as a result?

Fully qualified name (which for non-namespaced classes is just class name) should be unique, this is PHP "limitation" and Composer autoloader relies on it. The best what you could get is to ignore one of these class using exclude-from-classmap setting:

"autoload": {
    "exclude-from-classmap": ["libraries/some-lib/Foo-alternate.php"]
}

Then Composer will autoload only class from libraries/some-lib/Foo.php. You may still load manually second class (require __DIR__ . '/libraries/some-lib/Foo-alternate.php'), but you should be really careful with this (this will result fatal error if libraries/some-lib/Foo.php is already loaded).