PSR4 auto load without composer

11,709

Solution 1

You have to read the composer and load the classes yourself for each namespaces defined into the composer.json.

Here is how :

function loadPackage($dir)
{
    $composer = json_decode(file_get_contents("$dir/composer.json"), 1);
    $namespaces = $composer['autoload']['psr-4'];

    // Foreach namespace specified in the composer, load the given classes
    foreach ($namespaces as $namespace => $classpaths) {
        if (!is_array($classpaths)) {
            $classpaths = array($classpaths);
        }
        spl_autoload_register(function ($classname) use ($namespace, $classpaths, $dir) {
            // Check if the namespace matches the class we are looking for
            if (preg_match("#^".preg_quote($namespace)."#", $classname)) {
                // Remove the namespace from the file path since it's psr4
                $classname = str_replace($namespace, "", $classname);
                $filename = preg_replace("#\\\\#", "/", $classname).".php";
                foreach ($classpaths as $classpath) {
                    $fullpath = $dir."/".$classpath."/$filename";
                    if (file_exists($fullpath)) {
                        include_once $fullpath;
                    }
                }
            }
        });
    }
}

loadPackage(__DIR__."/vendor/project");

new CompanyName\PackageName\Test();

Of course, I don't know the classes you have in the PackageName. The /vendor/project is where your external library was cloned or downloaded. This is where you have the composer.json file.

Note: this works only for psr4 autoload.

EDIT : Adding support for multiple classpaths for one namespace

EDIT2 : I created a Github repo to handle this code, if anyone wants to improve it.

Solution 2

Yes, this question is 6months old, however I just used the following. I just found the following solution to the problem. I just locally ran the command composer dump-autoload -o in my project folder. After that I simply had to upload the contents of ./vendor/composer folder and the /vendor/autoload.php to the server and it worked again. This is helpful in case you cannot run composer on the server.

Solution 3

I am not a fan of Composer for many reasons. 1st reason shared hosting services do not offer composer as a package therefor it makes it harder to deliver low budget applications or simple MVC custom frameworks. Here is a work around that is compliant with PSR4 standards.

Assuming you add this auto-load method in a file in the root directory and that we are auto-loading classes for everything inside a folder called "src" here is how to archive this.

define('ROOT', dirname(__DIR__));
define('SLASH', DIRECTORY_SEPARATOR);

spl_autoload_register(function ($className) 
{
    $fileName = sprintf("%s%ssrc%s%s.php", ROOT, SLASH, SLASH, str_replace("\\", "/", $className));

    if (file_exists($fileName)) 
    {
        require ($fileName);
    } 
    else 
    {
        echo "file not found {$fileName}";
    }
});

now in every file you should add a namespace and if you have a dependency the use. here is a basic example in

namespace myapp;
use Core\Example;

Also, all your folders inside src should start with a capital letter in my example.

and done. Cheers @jerryurenaa

Share:
11,709
Happy Coder
Author by

Happy Coder

Updated on July 27, 2022

Comments

  • Happy Coder
    Happy Coder almost 2 years

    I have one package in a project which is autoloaded using composer and composer.json entry is as follows :

     "autoload": {
          "psr-4": {
            "CompanyName\\PackageName\\": "packages/package-folder/src/"
        }
      }
    

    Now I am copying this over to another project which is not using composer. How can I autoload this same package there ?