Search code examples
phpcomposer-phppackagist

Composer autoload - files option and packagist


I've already developed several composer modules which I've published successfully to packagist.

All of them are fully class based, and I know how the autoloading process works for those - if multiple projects use my packagist module, they will be included only once.

Does it work the same for files?

I want to develop a packagist module for "missing" WordPress functions - i.e. functions I regularly use across all of my projects.

If multiple projects include that packagist module, will I get errors about multiple definitions of the same function in a same namespace?

Clarification.

I'm creating a composer module sgi/wp-utils. It won't have classes. It will only include files. Like this

{
    "autoload": {
        "files": [
            "src/Assets/functions.php",
            "src/Posts/functions.php"
         ]
    }
}

It will be used to define utility functions I plan to use across many projects (plugins, themes).

If multiple plugins / themes use the same package, will composer load files only once per WP installation, or I need to wrap functions with function_exists() calls?


Solution

  • If multiple packages within the same composer project require the same package, the dependency will be resolved and the package will be included only once, and the files in the files key of composer.json:

    {
        "autoload": {
            "files": ["src/MyLibrary/functions.php"]
        }
    }
    

    will not be included more than once anyway. This is not really "autoloading", since there is really no autoloading for "functions" in PHP, but simply that these files will be "included" on each request that requires the main autoload.php script.

    Since you mention Wordpress, in that world thing can get trickier, since multiple plugins will be separate Composer projects, each with their own declared dependencies which will be loaded in parallel.

    If multiple plugins have their own composer.json file declared, and they use the same package, they will attempt to load multiple copies of the same files, and define the same classes and functions again. This can lead to clashes with classnames and function names.

    Even if the autoloader used something like include_once (which it doesn't), it wouldn't work. Since each plugin would have its own copy of the package, and would be including different files.

    You can take some basic precautions, like wrapping your function declarations within if (!function_exists('my_function') { }. Something like:

    <?php
    
    if (function_exists('foo')) {
        return;
    }
    
    function foo() {
       echo "foo";
    }
    

    to avoid fatal errors when attempting to define an already defined function).

    This will avoid attempting to define the same function twice, but you could also hit trouble if several plugins depend on different and incompatible versions of the same package.

    Wordpress and Composer are simply not very good bedfellows, since Wordpess is very poorly adjusted to the modern-way to manage dependencies in the wider PHP ecosystem.