1
votes

I have a legacy project that uses the "files" section inside of the "autoload" definition for some initialization. This initialization depends on some framework. What I'm trying to do is to make the few unit tests of this codebase runnable without having the framework be present. The code of my legacy project gets loaded via a mix of "psr-4" and "classmap" inside of "autoload". Furthermore, this project depends on a number of libraries loaded via Composer.

This means I can't just include the composer autoloader (vendor/autoload.php) in my test bootstrap as I'd normally do. I've had a go at including just the classmap, namespace and psr-4 loaders in vendor/composer, though after some digging in the Composer code found it's not that simple.

Is there a somewhat-sane way to use the Composer generated autoloader without having it include the "files" defined in the "autoload" section?

1
You could simply load the autoload_classmap.php from the vendor/composer/ folder? I mean guess that could work. Or whatever file you need from there.Andrei
It's not that simple. These files don't actually load anything, they just return a spec of what should be loaded. I could of course register those with the Composer autoloading class, though am hoping there is a nicer approach.Jeroen De Dauw
Is there ever a nice approach with legacy projects? Don't answer that, rhetorical question. You could register an spl autoloader? At least it has the benefit of not actually loading the classes until they're needed, but then again so does composer...Andrei

1 Answers

0
votes

A workable though not so nice solution is to create an instance of the Composer autoloader yourself and register the psr-4, classmap and psr-0 definitions yourself.

Assuming your test bootstrap is in a subdirectory of your project root, the following code should work:

require __DIR__ . '/../vendor/composer/ClassLoader.php';

call_user_func( function() {
    $loader = new \Composer\Autoload\ClassLoader();

    foreach ( require __DIR__ . '/../vendor/composer/autoload_namespaces.php' as $namespace => $path ) {
        $loader->set( $namespace, $path );
    }

    foreach ( require __DIR__ . '/../vendor/composer/autoload_psr4.php' as $namespace => $path ) {
        $loader->setPsr4( $namespace, $path );
    }

    $classMap = require __DIR__ . '/../vendor/composer/autoload_classmap.php';

    if ( $classMap ) {
        $loader->addClassMap( $classMap );
    }

    $loader->register( true );
} );

This will never make use of the "static initialization" codepath from the Composer autoloader. As far as I can tell that is just there for optimization purposes, so this should not be an issue for tests.