Programster
Programster

Reputation: 12814

Package Autoloading Issues

I'm struggling to work out how to correctly build and autoload my first composer package. I understand that if I follow the PSR-0 naming convention, autoloading should "just work". I am trying to set up with:

I have managed to debug a project that includes the package to the point where I am outputting the search path by putting a print in the findFileWithExtension() function of the ClassLoader.php file

/home/stuart/Desktop/test-project/vendor/Programster/CoreLibs/Programster/Programster/CoreLibs/Core.php

I know that the file is actually located at:

/home/stuart/Desktop/test-project/vendor/Programster/CoreLibs/Core.php

My Package's composer.json file:

{
    "name": "Programster/CoreLibs",
    "type": "library",
    "description": "Core libraries for PHP 5.3+",
    "keywords": ["core","library"],
    "homepage": "http://svn.yadda-yadda.com/php/core-libs",
    "license": "none",
    "authors": [
        {
            "name": "xxxx",
            "email": "[email protected]",
            "homepage": "http://mywebsite.com/",
            "role": "Developer"
        }
    ],
    "require": {
        "php": ">=5.3.0"
    },
    "autoload": {
        "psr-0": {
            "Programster": "Programster"
        }
    }
}

The following is a tiny script in a project that includes the package to test if is working:

<?php

require_once(__DIR__ . '/../vendor/autoload.php');

$loader = new \Composer\Autoload\ClassLoader();
$loader->register();

use \Programster\CoreLibs as programster;
programster\Core::println("hello world");

The project's composer.json file to include the package:

{
    "repositories": [ { "type": "composer", "url": "http://satis.mydomain.com/" } ],
    "require": {
        "Programster/CoreLibs": "dev-trunk"
    }
}

Is my package's config wrong, or do I really need to create Programster/CoreLibs/ subdirectories within the CoreLibs repository source code?

Upvotes: 0

Views: 87

Answers (2)

Sven
Sven

Reputation: 70923

use \Programster\CoreLibs as programster;
programster\Core::println("hello world");

Your class name evaluates to \Programster\CoreLibs\Core.

With this PSR-0 autoloading,

    "psr-0": {
        "Programster": "Programster"
    }

the class name will be completely converted into a path name like "Programster/CoreLibs/Core.php", and this path will be searched inside the directory "Programster" relative to your libraries composer.json location.

Using PSR-4 autoloading,

    "psr-4": {
        "Programster\\CoreLibs\\": ""
    }

the prefix in this definition will be removed from the classname, the remainder will be converted to a path (i.e. "Core.php") and be searched in the path mentioned (in this case, in the main directory of the library, because "" + "Core.php" is pointing to a file in without any sub directory).

Your second definition is better in some regards. It uses a longer prefix, which is relevant if you include more than one library using the same prefix, because then Composer would have to search more than one path to find the class. And it uses a shorter path, which also allows for slightly faster disk I/O operations (I haven't done any performance measurements, though).

Upvotes: 1

Programster
Programster

Reputation: 12814

I managed to get it working by using the PSR-4 standard that others suggested in the comments and updating my package's composer.json file (see the autoload section):

{
    "name": "Programster/CoreLibs",
    "type": "library",
    "description": "Core libraries for PHP 5.3+",
    "keywords": ["core","library"],
    "homepage": "http://svn.mydomain/core-libs",
    "license": "none",
    "authors": [
        {
            "name": "MY name",
            "email": "[email protected]",
            "homepage": "http://my-website.com/",
            "role": "Developer"
        }
    ],
    "require": {
        "php": ">=5.3.0"
    },
    "autoload": {
        "psr-4": {
            "Programster\\CoreLibs\\": ""
        }
    }
}

This is my script in the project that has the package installed:

require_once(__DIR__ . '/../vendor/autoload.php');
\Programster\CoreLibs\Core::println("hello world");

@sectus was right, I did not need to use $loader = new \Composer\Autoload\ClassLoader();$loader->register();

Upvotes: 0

Related Questions