Towards A Package-Oriented Autoloader

516 views
Skip to first unread message

Paul Jones

unread,
Mar 27, 2013, 12:36:37 AM3/27/13
to php...@googlegroups.com
Hi everyone,

Please consider this essay a pre-proposal to gauge interest, especially among Composer users. This is *not* a call to end PSR-0; it is to suggest that it may make sense to provide an additional alternative.


tl;dr
-----

It may be useful to provide a package-oriented autoloader reference wherein:

1. Implementors MUST use at least two namespace levels: a vendor name, and package name within that vendor. (This top-level two-name combination is hereinafter referred to as the vendor-package name or the vendor-package namespace.)

2. Implementors MUST allow a path infix between the vendor-package namespace and the remainder of the fully qualified class name.

3. The vendor-package namespace MAY map to any directory. The remaining portion of the fully-qualified class name MUST map the namespace names to identically-named directories, and MUST map the class name to an identically-named file ending in .php.

Note that this means no direct class-to-file mapping, and that underscores in class names would not be honored as directory separators.


History of PSR-0
----------------

The PSR-0 class naming and autoloading standard rose out of the broad acceptance of the Horde/PEAR convention under the constraints of PHP 5.2 and previous. With that convention, the tendency was to put all PHP source classes in a single main directory, using underscores in the class name to indicate pseudo-namespaces, like so:

/path/to/src/
VendorFoo/
Bar/
Baz.php # VendorFoo_Bar_Baz
VendorDib/
Zim/
Gir.php # Vendor_Dib_Zim_Gir

With the release of PHP 5.3 and the availability of namespaces proper, PSR-0 was introduced to allow both the old Horde/PEAR underscore mode *and* the use of the new namespace notation. Underscores were still allowed in the class name to ease transition from the older namespace naming to the newer naming, and thereby to encourage wider adoption.

/path/to/src/
VendorFoo/
Bar/
Baz.php # VendorFoo_Bar_Baz
VendorDib/
Zim/
Gir.php # VendorDib_Zim_Gir
Irk_Operation/
Impending_Doom/
V1.php
V2.php # Irk_Operation\Impending_Doom\V2

This structure is informed very much by the fact that the PEAR installer moved source files from PEAR packages into a single central directory.


Along Comes Composer
--------------------

With Composer, package sources are no longer copied to a single central location. They are used from their installed location and are not moved around. This means that with Composer there is no "single main directory" for PHP sources as with PEAR. Instead, there are multiple directories, one for each package.

To meet the requirements of PSR-0, this leads to Composer packages looking like this:

vendor/
vendor_name/
package_name/
src/
Vendor_Name/
Package_Name/
ClassName.php # Vendor_Name\Package_Name\ClassName
tests/
Vendor_Name/
Package_Name/
ClassNameTest.php # Vendor_Name\Package_Name\ClassNameTest

The "src" and "tests" directories have to include vendor and package directory names. This is an artifact of PSR-0 compliance.

Many find this structure to be deeper and more-repetitive than necessary. I suggest that an additional or superseding PSR would be useful so that we can have packages that look more like the following:

vendor/
vendor_name/
package_name/
src/
ClassName.php # Vendor_Name\Package_Name\ClassName
tests/
ClassNameTest.php # Vendor_Name\Package_Name\ClassNameTest

This would require an implementation of what I will call "package-oriented autoloading" (as vs the traditional "direct class-to-file autoloading").


Package-Oriented Autoloading
----------------------------

It's difficult to implement package-oriented autoloading via an extension or amendment to PSR-0, because PSR-0 does not allow for an intercessory path between any portions of the class name. This means the implementation of a package-oriented autoloader would be more complicated than PSR-0. However, it would allow for cleaner packages.

I suggest the following rules:

1. Implementors MUST use at least two namespace levels: a vendor name, and package name within that vendor. (This top-level two-name combination is hereinafter referred to as the vendor-package name or the vendor-package namespace.)

2. Implementors MUST allow a path infix between the vendor-package namespace and the remainder of the fully qualified class name.

3. The vendor-package namespace MAY map to any directory. The remaining portion of the fully-qualified class name MUST map the namespace names to identically-named directories, and MUST map the class name to an identically-named file ending in .php.

Note that this means the end of underscore-as-directory-separator in the class name. Normally I would say underscores should be honored as they are under PSR-0, but seeing as their presence in that document is in reference to transitioning away from PHP 5.2 and previous pseudo-namespacing, I think it is acceptable to remove them here as well.


Examples
--------

Given the above vendor-package structure, one would add a vendor-package to the package-oriented autoloader like so:

$loader = new PackageOrientedAutoloader;

$loader->addPackage(

// the vendor-package namespace
'Vendor_Name\Package_Name',

// path to source files for the package
'/path/to/vendor_name/package_name/src'
);

The actual loading logic would look through registered package namespaces to match the fully-qualified class name with a package source directory.

This would still be compatible with PSR-0 systems, *provided* it had at least two namespace levels and no underscores in class names. One would add a vendor-package like this (note the extra two directories at the end of the path):

$loader->addPackage(

// vendor-and-package namespace
'Vendor_Name\Package_Name',

// path to source files
'/path/to/vendor_name/package_name/src/Vendor_Name/Package_Name'
);

See below for an example implementation of the above rules, along with a mock for testing and a PHPUnit test. (You can copy all of these into a single file and invoke it with PHPUnit.)

That is all; code follows.

* * *

<?php
class PackageOrientedAutoloader
{
// paths for a vendor-package
protected $paths = array();

// add a path for a vendor-and-package namespace prefix
public function addPackage($vp, $path)
{
$path = rtrim($path, DIRECTORY_SEPARATOR);
$this->paths[$vp][] = $path;
}

// load a fully-qualified class name
public function load($fqcn)
{
// explode the fully-qualified class name into separate parts
$parts = explode('\\', $fqcn);

// get the vendor-package parts (elements 0 and 1)
$vp = array_shift($parts) . '\\' . array_shift($parts);

// is the vendor-package in the paths?
if (! isset($this->paths[$vp])) {
// no
return false;
}

// convert the remaining parts to a partial file name
$name = implode(DIRECTORY_SEPARATOR, $parts) . '.php';
// go through each of the paths for the vendor-package
foreach ($this->paths[$vp] as $path) {
// create a complete file name from the path and partial name
$file = $path . DIRECTORY_SEPARATOR . $name;
// is it readable?
if ($this->readFile($file)) {
return true;
}
}

// never found it
return false;
}

// read a file from the filesystem
protected function readFile($file)
{
if (! is_readable($file)) {
return false;
}

require $file;
return true;
}
}

class MockPackageOrientedAutoloader extends PackageOrientedAutoloader
{
protected $files = array();

public function setFiles(array $files)
{
$this->files = $files;
}

protected function readFile($file)
{
return in_array($file, $this->files);
}
}

class PackageOrientedAutoloaderTest extends PHPUnit_Framework_TestCase
{
protected $loader;

protected function setUp()
{
$this->loader = new MockPackageOrientedAutoloader;

$this->loader->setFiles(array(
'/vendor/vendor_name/package_name/src/ClassName.php',
));

$this->loader->addPackage(
'Vendor_Name\Package_Name',
'/vendor/vendor_name/package_name/src'
);
}

public function testExistingFile()
{
$actual = $this->loader->load('Vendor_Name\Package_Name\ClassName');
$this->assertTrue($actual);
}

public function testMissingFile()
{
$actual = $this->loader->load('No_Vendor\No_Package\NoClass');
$this->assertFalse($actual);
}
}

Alexandre Gaigalas

unread,
Mar 27, 2013, 2:26:25 AM3/27/13
to php...@googlegroups.com
I agree on making it separate from PSR-0 (even though I'm not anything like a voting member. Just expressing an opinion).

This (as a hypothetical update to PSR-0) is particularly bad for one of my projects. We tend to use a custom PSR-0 compatible autoloader that relies on the include_path instead of the path mechanism of the reference implementation.

We support both PEAR and Composer with automatically generated packages and channels with that setup and encourage this as one of the possible setups in our docs. We test and benchmark using this setup.

This change would make my implementation from compatible to incompatible and a huge change would be necessary. As a separate spec there is no problem at all.

It seems that PEAR have already solved this with the specific folders for each file role. Considering this is a wide deployed solution and there are efforts to make hybrid Composer/PEAR package installers (https://github.com/c9s/Onion), wouldn't be rational to follow the compatibility road of standards and design an analog to the PEAR roles?

I particularly thought of this specific problem while designing an open source automation tool for PHP. We ended up creating a static step that guesses the folder structure from common names (src, lib, test, doc, library, tests, etc) and mirroring that on the PEAR package creation (sample: https://github.com/Respect/Foundation/blob/master/src/Respect/Foundation/InfoProviders/LibraryFolder.php). We used an early version of Onion.

The point is that making a new standard while keeping some sort of compatibility could help efforts like these that have the same goal but already made some progress. I'm sure a lot of custom proprietary solutions, Makefiles, Phing implementations, Travis-related tools and similar heavy users of packaging could benefit from this as well.

Hope my thoughts could help the discussion. It's really not intended to cause confusion.

--
Gaigalas




--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.



Paul Jones

unread,
Mar 27, 2013, 2:33:46 AM3/27/13
to php...@googlegroups.com

On Mar 26, 2013, at 8:26 PM, Alexandre Gaigalas wrote:

> I agree on making it separate from PSR-0 (even though I'm not anything like a voting member. Just expressing an opinion).

Sure -- *if* anyone else thinks this is a good idea, it would have to be separate from PSR-0.


> It seems that PEAR have already solved this with the specific folders for each file role.

That's part of the point of the essay -- with PEAR, things get moved around at installation time. With Composer (and perhaps with future packaging systems) they stay in place.


> Considering this is a wide deployed solution and there are efforts to make hybrid Composer/PEAR package installers (https://github.com/c9s/Onion), wouldn't be rational to follow the compatibility road of standards and design an analog to the PEAR roles?

I think it would be useful, at some point, to have a reference for what a package should look like in terms of directory names inside that package. I am partial to the PEAR names, given my history. However, the essay does not address that, and I don't think it falls within its scope.


-- pmj

Alexandre Gaigalas

unread,
Mar 27, 2013, 3:51:13 AM3/27/13
to php...@googlegroups.com
You're right. =)

Donald Gilbert

unread,
Mar 27, 2013, 4:08:07 AM3/27/13
to php...@googlegroups.com
pmjones, you asterisked your if as though the fact that others would support this were in question, which couldn't be further from reality. PSR-0 is not the be-all end-all for autoloaders. Coming from Joomla, we had an advanced autoloader that already fixed these issues trying to be fixed here, and we digressed to use the composer PSR-0 autoloader for our packages.

The fix for this is as simple as stripping off the registered namespace from the FQCN when loading. So if I register('Joomla\Name\Space', __DIR__ . '/src'), when it hits the autoloader, it strips off "Joomla\Name\Space", and starts its search from that point, in the registered directories. It only makes sense to do it this way, and totally removes the multiple unnecessary folders within a package src directory.

Paul Jones

unread,
Mar 27, 2013, 4:16:01 AM3/27/13
to php...@googlegroups.com

On Mar 26, 2013, at 10:08 PM, Donald Gilbert wrote:

> pmjones, you asterisked your if as though the fact that others would support this were in question, which couldn't be further from reality. PSR-0 is not the be-all end-all for autoloaders. Coming from Joomla, we had an advanced autoloader that already fixed these issues trying to be fixed here, and we digressed to use the composer PSR-0 autoloader for our packages.
>
> The fix for this is as simple as stripping off the registered namespace from the FQCN when loading. So if I register('Joomla\Name\Space', __DIR__ . '/src'), when it hits the autoloader, it strips off "Joomla\Name\Space", and starts its search from that point, in the registered directories. It only makes sense to do it this way, and totally removes the multiple unnecessary folders within a package src directory.

I'll take that as a "yes, at least one person thinks it is a good idea." ;-)


-- pmj

Donald Gilbert

unread,
Mar 27, 2013, 5:32:55 AM3/27/13
to php...@googlegroups.com
:)
Message has been deleted

Max Roeleveld

unread,
Mar 27, 2013, 7:44:38 AM3/27/13
to php...@googlegroups.com

On Wednesday, March 27, 2013 12:36:37 AM UTC+1, pmjones wrote:

Please consider this essay a pre-proposal to gauge interest,

Consider me interested. =]

Max

Beau Simensen

unread,
Mar 27, 2013, 8:20:58 AM3/27/13
to php...@googlegroups.com
On Tuesday, March 26, 2013 6:36:37 PM UTC-5, pmjones wrote:
Please consider this essay a pre-proposal to gauge interest, especially among Composer users. This is *not* a call to end PSR-0; it is to suggest that it may make sense to provide an additional alternative. 

Nice! Have you seen Igor Wiedler's thoughts on this? From a high level it looks like you have similar things in mind.



Many find this structure to be deeper and more-repetitive than necessary.

As it looks like this comment is aimed directly at how Composer unpacks packages into vendor/ I have to ask... why do humans care how deep and repetitive the directory structure under a Composer managed vendor/ gets? I have heard this come up many times but I have not heard any good reasons why any people should care.

If this is about people wanting to maintain their own project as src/Baz instead of src/Foo/Bar/Baz, great. People are already sort of getting away with that by using the target-dir directive with Composer. I would question anything aimed primarily at "cleaning up Composer's vendor/ directory," though.


In general I think that it would be nice to see people discussing some alternatives to PSR-0 in cases where PSR-0 either doesn't make sense or is not desirable. Composer already offers a few alternatives. I've wondered if we could find a way to add custom autoloaders to Composer. Maybe that is already possible? I haven't checked lately. I'm thinking similar to installers where a project could specify its autoloader package as a required dependency and that autoloader package, when installed, would automatically get hooked into `vendor/autoload.php` somehow.

Jordi Boggiano

unread,
Mar 27, 2013, 10:45:16 AM3/27/13
to php...@googlegroups.com
Heya,

> 1. Implementors MUST use at least two namespace levels: a vendor
> name, and package name within that vendor. (This top-level two-name
> combination is hereinafter referred to as the vendor-package name or
> the vendor-package namespace.)

Not so keen on that one. We went from a wild-west situation to PSR-0
which enforces a vendor. That's cool. But then for libraries (i.e. not
frameworks) having a vendor + package makes no sense to me. Stuff like I
can think of class names in my projects like: Composer\Factory,
Monolog\Logger. Those are "namespaced" within their own vendor. They
don't need an extra duplication of the vendor name as package name IMO.

> 2. Implementors MUST allow a path infix between the vendor-package
> namespace and the remainder of the fully qualified class name.
>
> 3. The vendor-package namespace MAY map to any directory. The
> remaining portion of the fully-qualified class name MUST map the
> namespace names to identically-named directories, and MUST map the
> class name to an identically-named file ending in .php.

Fine with those, and the overall technical idea of saying namespace Foo
is to be found in whatever/. Right now I know a bunch of people are
confused with composer configs, because you essentially have to say
where a namespace is "rooted", instead of where the namespace's contents
are (Foo => src/ vs Foo => src/Foo).

Now whether this is a really great progress or not. I have mixed
feelings there. It's not a huge deal to have a couple extra dirs and
PSR-0 just works even though it's not the leanest solution.

Cheers

--
Jordi Boggiano
@seldaek - http://nelm.io/jordi

Paul Jones

unread,
Mar 27, 2013, 3:04:56 PM3/27/13
to php...@googlegroups.com

On Mar 27, 2013, at 4:45 AM, Jordi Boggiano wrote:

> Heya,
>
>> 1. Implementors MUST use at least two namespace levels: a vendor
>> name, and package name within that vendor. (This top-level two-name
>> combination is hereinafter referred to as the vendor-package name or
>> the vendor-package namespace.)
>
> Not so keen on that one. We went from a wild-west situation to PSR-0
> which enforces a vendor. That's cool. But then for libraries (i.e. not
> frameworks) having a vendor + package makes no sense to me. Stuff like I
> can think of class names in my projects like: Composer\Factory,
> Monolog\Logger. Those are "namespaced" within their own vendor. They
> don't need an extra duplication of the vendor name as package name IMO.

And yet they are duplicated in the Composer package name, composer/composer. ;-)

That joke aside, I hear you. Note that the essay is not an attempt to replace PSR-0; it is an additional alternative to PSR-0. That means Monolog, for example, can still use PSR-0 if it like.

But notice that at least *some* library authors represented here do make use of the two-level system: a top-level vendor name to indicate the author/community/project, and a second level package name to indicate the particular library within that context. Indeed, Composer itself (in the package naming it requires) mimics that. The essay addresses that approach.



>> 2. Implementors MUST allow a path infix between the vendor-package
>> namespace and the remainder of the fully qualified class name.
>>
>> 3. The vendor-package namespace MAY map to any directory. The
>> remaining portion of the fully-qualified class name MUST map the
>> namespace names to identically-named directories, and MUST map the
>> class name to an identically-named file ending in .php.
>
> Fine with those, and the overall technical idea of saying namespace Foo
> is to be found in whatever/. Right now I know a bunch of people are
> confused with composer configs, because you essentially have to say
> where a namespace is "rooted", instead of where the namespace's contents
> are (Foo => src/ vs Foo => src/Foo).
>
> Now whether this is a really great progress or not. I have mixed
> feelings there. It's not a huge deal to have a couple extra dirs and
> PSR-0 just works even though it's not the leanest solution.

Again, I hear you. Even so, I think the essay recognizes an actual problem, even if some folks think that problem is small in the grand scheme, and I think its worth addressing.


-- pmj

Jordi Boggiano

unread,
Mar 27, 2013, 3:10:58 PM3/27/13
to php...@googlegroups.com
On 27.03.2013 15:04, Paul Jones wrote:
> But notice that at least *some* library authors represented here do
> make use of the two-level system: a top-level vendor name to indicate
> the author/community/project, and a second level package name to
> indicate the particular library within that context. Indeed,
> Composer itself (in the package naming it requires) mimics that. The
> essay addresses that approach.

I agree it makes sense for many people to do it. I just don't see any
technical argument for this new spec to enforce it.

The vendor name brings namespacing which is good. Within one vendor I
think people should be free to organize things as they please.

Paul Jones

unread,
Mar 27, 2013, 4:02:04 PM3/27/13
to php...@googlegroups.com

On Mar 27, 2013, at 9:10 AM, Jordi Boggiano wrote:

> On 27.03.2013 15:04, Paul Jones wrote:
>> But notice that at least *some* library authors represented here do
>> make use of the two-level system: a top-level vendor name to indicate
>> the author/community/project, and a second level package name to
>> indicate the particular library within that context. Indeed,
>> Composer itself (in the package naming it requires) mimics that. The
>> essay addresses that approach.
>
> I agree it makes sense for many people to do it. I just don't see any
> technical argument for this new spec to enforce it.

Fair; all I'm saying is that it appears to be a common practice among the voting members here, and since this groups was formed to find commonalities and codify them, it makes sense to me to recognize it.


-- pmj

Larry Garfield

unread,
Mar 29, 2013, 4:18:00 AM3/29/13
to php...@googlegroups.com
General answer:

This is a concern that has been brought up several times in Drupal, so
yes we're very interested. At present we're using strict PSR-0
(something I've tried to hold very firm on for the "forcing off the
island" value), but there is general consensus that the resulting path
structures are crazy deep.

Beau: as an example of where it becomes a problem, consider this excerpt
of the Drupal 8 file structure:

/core
/lib [where we're putting core classes]
/Drupal
/Component
/Core
/Routing
/UrlGenerator.php
/modules
/user
/lib
/Drupal
/user
/TempStore.php
/vendor
/symfony
/http-foundation
/Symfony
/Component
/HttpFoundation
/Request.php
/http-kernel
/Symfony
/Component
/HttpKernel
/HttpKernelInterface.php
/doctrine
/common
/lib
/Doctrine
/Common
/Lexer.php
...

It really is way too deep, and since we're pulling in Symfony components
piecemeal it means they're all spread out into different way too deep
paths. The computer doesn't care, but people typing cd on the command
line or clicking open + signs in their IDE do care. And for module
developers it is a pain to have to double your module name.

Naturally we can't change what vendor libs are doing, but a FIG-approved
way to have fewer directories within modules would be very welcome.

Specifics:

That said, I'm not sure that requiring two namespaces at the top is the
best way to do it. Sure PSR-0 still works, cool, whatev, but it seems
that the cleaner approach would be to allow the registered namespace
root to be omitted from the directory tree. That is, the following would
all find the example class below:

$loader->register('\Drupal', '/some/dir/');
$loader->register('\Drupal\mymodule', '/some/dir/mymodule');
$loader->register('\Drupal\mymodule\Controller',
'/some/dir/mymodule/Controller');

/some/dir/mymodule/Controller/Hi.php

namespace Drupal\mymodule\Controller;
class Hi {}

That would allow us, in the Drupal case, to register $module_dir/lib/ as
the root for \Drupal\$module_name, resulting in:

/core
/modules
/user
/lib
/TempStore.php (contains \Drupal\user\Tempstore)

That is, cutting out two redundant layers of directory. I could already
name a number of Drupalers that would be very happy to see that.

So give or take specifics, yes, very much interested.

Additional notes:

I'm perfectly happy to see the underscores=>directory mapping go away;
that's just a BC feature anyway that wouldn't be needed here.

You get bonus points for gratuitous Invader Zim references.

--Larry Garfield

Paul Jones

unread,
Mar 29, 2013, 5:50:09 PM3/29/13
to php...@googlegroups.com

On Mar 28, 2013, at 10:18 PM, Larry Garfield wrote:

> This is a concern that has been brought up several times in Drupal, so yes we're very interested. At present we're using strict PSR-0 (something I've tried to hold very firm on for the "forcing off the island" value), but there is general consensus that the resulting path structures are crazy deep.
...
> I'm not sure that requiring two namespaces at the top is the best way to do it. Sure PSR-0 still works, cool, whatev, but it seems that the cleaner approach would be to allow the registered namespace root to be omitted from the directory tree.
...
> I'm perfectly happy to see the underscores=>directory mapping go away; that's just a BC feature anyway that wouldn't be needed here.


I get you on the "two namespaces" thing. The best thing about it is that it sets up an easy-to-predict situation; the worst thing is that it forces you into a specific situation.

Before I sent the essay, I toyed with the idea you bring up. Instead of two namespaces, there could be an arbitrary number of namespaces.

The problem is that it would be possible to register Foo\Bar, and then Foo\Bar\Baz\Dib, and then Foo\Bar\Baz\Dib\Zim\Gir with separate locations. Thus, we would need to decide which one gets precedence.

In playing around with it, I opted for "deepest registered namespace takes precedence, then work your way back up." Below my sig line, you can see what one possible implementation would look like . The major change is to the load() method.


> You get bonus points for gratuitous Invader Zim references.

/me bows


-- pmj


----- FILE BEGINS -----

<?php
class NamespaceOrientedAutoloader
{
// paths for a namespace
protected $paths = array();

// add a path for a namespace
public function addNamespace($ns, $path)
{
$path = rtrim($path, DIRECTORY_SEPARATOR);
$this->paths[$ns][] = $path;
}

// load a fully-qualified class name
public function load($fqcn)
{
// a partial file name for the class
$name = '';

// go through the parts of the fully-qualifed class name
$parts = explode('\\', $fqcn);
while ($parts) {

// take the last element off the fully-qualified class name
// and add to the partial file name. always have a leading
// directory separator here.
$name = $name . DIRECTORY_SEPARATOR . array_pop($parts);

// the remaining parts indicate the registered namespace
$ns = implode('\\', $parts);

// is the namespace registered?
if (! isset($this->paths[$ns])) {
// no, continue the loop
continue;
}

// the namespace is registered. look through its paths.
foreach ($this->paths[$ns] as $path) {

// create a complete file name from the path and partial name
$file = $path . $name . '.php';

// can we read the file from the filesystem?
if ($this->readFile($file)) {
// yes, we're done
return true;
}
}
}

// never found a file for the class
return false;
}

// read a file from the filesystem
protected function readFile($file)
{
if (! is_readable($file)) {
return false;
}

require $file;
return true;
}
}

class MockNamespaceOrientedAutoloader extends NamespaceOrientedAutoloader
{
protected $files = array();

public function setFiles(array $files)
{
$this->files = $files;
}

protected function readFile($file)
{
return in_array($file, $this->files);
}
}

class NamespaceOrientedAutoloaderTest extends PHPUnit_Framework_TestCase
{
protected $loader;

protected function setUp()
{
$this->loader = new MockNamespaceOrientedAutoloader;

$this->loader->setFiles(array(
'/vendor/foo.bar/src/ClassName.php',
'/vendor/foo.bar.baz.dib/src/ClassName.php',
'/vendor/foo.bar.baz.dib.zim.gir/src/ClassName.php',
'/vendor/psr0/package/src/Psr0/Package/File.php',
));

$this->loader->addNamespace(
'Foo\Bar',
'/vendor/foo.bar/src'
);

$this->loader->addNamespace(
'Foo\Bar\Baz\Dib',
'/vendor/foo.bar.baz.dib/src'
);

$this->loader->addNamespace(
'Foo\Bar\Baz\Dib\Zim\Gir',
'/vendor/foo.bar.baz.dib.zim.gir/src'
);

$this->loader->addNamespace(
'Psr0\Package',
'/vendor/psr0/package/src/Psr0/Package'
);
}

public function testExistingFile()
{
$actual = $this->loader->load('Foo\Bar\ClassName');
$this->assertTrue($actual);
}

public function testPsr0File()
{
$actual = $this->loader->load('Psr0\Package\File');
$this->assertTrue($actual);
}

public function testMissingFile()
{
$actual = $this->loader->load('No_Vendor\No_Package\NoClass');
$this->assertFalse($actual);
}

public function testDeepFile()
{
$actual = $this->loader->load('Foo\Bar\Baz\Dib\Zim\Gir\ClassName');
$this->assertTrue($actual);
}
}

----- FILE ENDS -----

Josh Hall-Bachner

unread,
Mar 29, 2013, 6:45:06 PM3/29/13
to php...@googlegroups.com
On Friday, March 29, 2013 9:50:09 AM UTC-7, pmjones wrote:

The problem is that it would be possible to register Foo\Bar, and then Foo\Bar\Baz\Dib, and then Foo\Bar\Baz\Dib\Zim\Gir with separate locations.  Thus, we would need to decide which one gets precedence.

In playing around with it, I opted for "deepest registered namespace takes precedence, then work your way back up."


I would much prefer the "arbitrary number of namespaces" option, and this is exactly the method I would prefer to resolve conflicts produced by it. I've gotten into the habit of defining a lot of internal projects by a three-level namespace like Vendor/ProjectArea/SpecificLibrary.

Beau Simensen

unread,
Apr 1, 2013, 6:00:29 AM4/1/13
to php...@googlegroups.com
Thanks Larry!

I guess what I meant by "why do people care," was, "why do people need to regularly visit anything under vendor/ such that it is a serious problem for them such that they need to complain about it and want to change it?"

I rarely run into this in my workflow and when I do I can navigate it pretty easily. This may be something to be discussed in a completely different setting, but it seems like maybe it is possible that this is more of a workflow issue and not so much a Composer/PSR-0 issue.

I won't comment too much on Drupal's directory depth because I haven't used it and not 100% sure I understand it. :)



For package managers I think this proposal makes a lot of sense. I get the feeling that many people would prefer to get rid of the cruft while they are actively developing a package. src/Foo/Bar/Baz.php is whack if everything is going to be inside of src/Foo/Bar. Just make it src/Baz.php and call it good! I can get behind that.

My main concern with this proposal is with it having anything to do with how Composer (or any package manager, for that matter) manages dependencies in a vendor/ like directory. Most of the examples specifically show vendor/vendor_name/package_name structures to showcase the depth problem and how this proposals fixes them. In my opinion these are implementation details very specific to Composer and really should not have any impact on the consumer of the dependencies.

If this is an issue because developers are consistently working in vendor/ then maybe that is a workflow issue with Composer. We might be better served addressing the source of the problem than trying to solve it with another autoloader proposal. I've struggled with this quite a bit and was (and to some extent, still is) one of my biggest pain points with Composer.


You get bonus points for gratuitous Invader Zim references. 

Agreed. I'm very sad to say I totally missed that on my first quick pass.


> I agree it makes sense for many people to do it. I just don't see any 
> technical argument for this new spec to enforce it. 
Fair; all I'm saying is that it appears to be a common practice among the voting members here, and since this groups was formed to find commonalities and codify them, it makes sense to me to recognize it. 

I'd definitely like to see this not be enforced by the spec. People and projects should be smart enough to know when it makes sense to create a project namespace and when not to. Sure, I can choose to use PSR-0 instead of PSR-X... but that isn't nice. I'd basically be having to choose between a shorter directory structure or an artificially longer namespace. Instead, I could just be choosing PSR-X solely because I want a shorter directory structure and not have to make any concessions on how my project is namespaced.


The problem is that it would be possible to register Foo\Bar, and then Foo\Bar\Baz\Dib, and then Foo\Bar\Baz\Dib\Zim\Gir with separate locations.  Thus, we would need to decide which one gets precedence. 

I want to say that Composer handles this depth first? I think that it would end up looking for Foo\Bar\Baz\Dib{\Zim\Gir} before Foo\Bar{\Baz\Dib\Zim\Gir}. I believe it actually contains an array for each level, too, so you could register multiple locations for each namespace. In that case I think "order of registering" takes precedence (not sure which order, though...).

I'd be curious to know how many people would think that it should be handled differently than how Composer is currently handling this type of situation. If nobody disagrees, it could probably be adopted for this proposal if we should decide to support arbitrary number of namespaces?

Paul Jones

unread,
Apr 1, 2013, 6:58:11 PM4/1/13
to php...@googlegroups.com

On Mar 31, 2013, at 11:00 PM, Beau Simensen wrote:

> I guess what I meant by "why do people care," was, "why do people need to regularly visit anything under vendor/ such that it is a serious problem for them such that they need to complain about it and want to change it?"

I suppose I should not have concentrated on Composer as the example case. The issue is not "vendor" per se, it is that packages (wherever they are stored, for whatever reasons) have this greater-than-really-needed depth that rises out of PSR-0 compliance. (PSR-0, in turn, was based on a single location for all source files instead of a package-oriented structure.)


> For package managers I think this proposal makes a lot of sense. I get the feeling that many people would prefer to get rid of the cruft while they are actively developing a package. src/Foo/Bar/Baz.php is whack if everything is going to be inside of src/Foo/Bar. Just make it src/Baz.php and call it good! I can get behind that.

Yes, exactly -- as well as for persons developing packages for those package managers.


> My main concern with this proposal is with it having anything to do with how Composer (or any package manager, for that matter) manages dependencies in a vendor/ like directory. Most of the examples specifically show vendor/vendor_name/package_name structures to showcase the depth problem and how this proposals fixes them. In my opinion these are implementation details very specific to Composer and really should not have any impact on the consumer of the dependencies.

On further consideration, I should not have written the essay with such a concentration on Composer. It's the easiest example to pick but it is of course only one implementation. For future reference, I think the followup suggestion by Larry for an arbitrary number of namespaces is probably the more correct one to pursue.


>> You get bonus points for gratuitous Invader Zim references.
>
> Agreed. I'm very sad to say I totally missed that on my first quick pass.

"With humor, my dear Zilkov! Always with a little humor." :-)


-- pmj

Phil Sturgeon

unread,
Apr 2, 2013, 4:11:49 AM4/2/13
to php...@googlegroups.com
I'd like to second the props for Invader Zim references, and second the suggestion of having this alternative autoloader.

PyroCMS moving across to PSR-2 has been fun, but challenging (still working on it) and while PSR-0 makes a lot of sense for a lot of the codebase, our modules look a little quirky:


Knocking out some extra folders could definitely help PyroCMS as it moves along. To the question above of "who is even looking under the vendor/ folder?" well the answer there is all of our module developers, who are the life-blood of our project. I like keeping them happy.

Now, for things like Laravel 4 having PSR-0 works really well, as the "laravel/framework" package does not line up with \Illuminate\Database\Eloquent\Model for example, but for smaller projects there is often a much closer connection between vendor/package and Vendor\Package, so this definitely makes sense.

Paul Jones

unread,
Apr 2, 2013, 5:07:42 AM4/2/13
to php...@googlegroups.com

On Apr 1, 2013, at 9:11 PM, Phil Sturgeon wrote:

> I'd like to second the props for Invader Zim references, and second the suggestion of having this alternative autoloader.
>
> PyroCMS moving across to PSR-2 has been fun, but challenging (still working on it) and while PSR-0 makes a lot of sense for a lot of the codebase, our modules look a little quirky:
>
> http://d.pr/i/uwQN
>
> Knocking out some extra folders could definitely help PyroCMS as it moves along. To the question above of "who is even looking under the vendor/ folder?" well the answer there is all of our module developers, who are the life-blood of our project. I like keeping them happy.

It seems like the CMS projects are definitely in favor of this idea, and of course I am; I don't recall hearing from library or framework projects proper, but even so, Aura at least could make good use of this. I'll start rolling up a draft.


-- pmj

Larry Garfield

unread,
Apr 2, 2013, 6:50:09 AM4/2/13
to php...@googlegroups.com
For vendor code, it is likely only relevant to core developers.  (There are several hundred of us, though.)  For them, it can be a challenge to track down a class from, say, Symfony's DI component that's even in a subdir under the DependencyInjection namespace; you have to do that at times, but it's some 8-10 directories down from your project root.

The bigger concern is for contributed modules, as every contrib author then has to put their module name and "Drupal" in their path a second time for... well, just because PSR-0 says they have to.  That gives us options of: 1) Add more directories that every contrib author must duplicate;  2) Use a different autoloader that's Drupal-specific.  I've argued that we do #1 as a "stop doing so much Drupal-specific stuff" wedge, but there is pushback.  I'd much rather have an option 3, "yay, fewer redundant directories".

Even if nothing in vendor was affected, that would still be an improvement for module developers.  (It sounds like Phil feels the same way for PyroCMS.)



My main concern with this proposal is with it having anything to do with how Composer (or any package manager, for that matter) manages dependencies in a vendor/ like directory. Most of the examples specifically show vendor/vendor_name/package_name structures to showcase the depth problem and how this proposals fixes them. In my opinion these are implementation details very specific to Composer and really should not have any impact on the consumer of the dependencies.

Composer makes the situation considerably worse with the way it organizes packages, but as noted above the depth problem exists even without it.  We don't use Composer for contributed modules, but it's definitely a concern for them nonetheless.

For a Silex project I'm working on currently, it's not a big deal; I have my /src/MyApp/ directory and everything's under that, and vendor is vendor.  It's fine.  For a plugin-based system, though, it is an issue.


> I agree it makes sense for many people to do it. I just don't see any 
> technical argument for this new spec to enforce it. 
Fair; all I'm saying is that it appears to be a common practice among the voting members here, and since this groups was formed to find commonalities and codify them, it makes sense to me to recognize it. 

I'd definitely like to see this not be enforced by the spec. People and projects should be smart enough to know when it makes sense to create a project namespace and when not to. Sure, I can choose to use PSR-0 instead of PSR-X... but that isn't nice. I'd basically be having to choose between a shorter directory structure or an artificially longer namespace. Instead, I could just be choosing PSR-X solely because I want a shorter directory structure and not have to make any concessions on how my project is namespaced.

It sounds like we're all leaning toward just extending PSR-0 to let you leave out some arbitrary number of directories, give or take implementation details for search order.  I think that's the best way forward.

--Larry Garfield

Amy Stephen

unread,
Apr 2, 2013, 9:38:13 PM4/2/13
to php...@googlegroups.com

I made the same type of recommendation a few months ago, Paul. Except, I recommend *not* using the src folder in the set up as it ends up introducing more layers.

I disagree, however, that it is a deviation from PSR-0, tho, it actually ends up implementing PSR-0 exactly like the examples show.


    vendor/
        vendor_name/
            package_name/  
                ClassName.php  

Ultimately, the reason we are not able to get those names is due to the lowercase restriction for vendor_name / package_name in Composer.

Documented here. https://gist.github.com/AmyStephen/4756621

Amy Stephen

unread,
Apr 2, 2013, 9:52:37 PM4/2/13
to php...@googlegroups.com
I made a small hack to the Composer.php file to get rid of these levels for my purpose https://github.com/Molajo/Standard/blob/master/ClassLoader.php#L233

Also a small performance tweak - https://github.com/Molajo/Standard/blob/master/ClassLoader.php#L184

When I get on top of things, was hoping to see what Jordi thought.

I also use a different folder structure - https://github.com/Molajo/Standard/tree/master/Vendor/Molajo/FieldHandler

No src folder - the package contains it just fine - then I put my tests, etc, into a .dev folder which works out nicely for tucking it away a bit.

In sum, that gets my path down to

Vendor/Molajo/FieldHandler/Type/Alpha

Instead of

Vendor/molajo/fieldHandler/Src/Molajo/FieldHandler/Type/Alpha



On Tuesday, March 26, 2013 6:36:37 PM UTC-5, pmjones wrote:

Paul Jones

unread,
Apr 2, 2013, 10:01:51 PM4/2/13
to php...@googlegroups.com

On Apr 2, 2013, at 2:38 PM, Amy Stephen wrote:

> I made the same type of recommendation a few months ago, Paul.

Ah yes! I remembered someone mentioning directory depth, but did not recall who it was. Do you have a link to the discussion thread?


-- pmj

Amy Stephen

unread,
Apr 2, 2013, 11:22:42 PM4/2/13
to php...@googlegroups.com
And with the link - a heads up - it's the ability to compare the reaction to how people responded to a woman raising the issue -- and when a man did the same -- that makes some of the more extreme feminists come unglued.

52 years old - 30+ years in the business. I found the response incredibly unkind and a lack of listening.

Please don't bother trying to explain why I was wrong, either. I know where I went wrong and I explained it. But this is a good learning experience for those of you who believe all women who act like they aren't taken seriously are sometimes correct.

https://groups.google.com/forum/#!msg/php-fig/-BPdegzme_Y/hyhqms-kz3oJ

Paul Jones

unread,
Apr 3, 2013, 1:08:52 AM4/3/13
to php...@googlegroups.com

On Apr 2, 2013, at 2:38 PM, Amy Stephen wrote:

> I disagree, however, that it is a deviation from PSR-0, tho, it actually ends up implementing PSR-0 exactly like the examples show.
>
>
> vendor/
> vendor_name/
> package_name/
> ClassName.php

Not quite. It can be used in any directory structure. The one you give would work, if registered with "vendor/vendor_name/package_name" as the root. However, the following would work too ...

Vendor.Package/
php-files/
FooBar.php
data-files/
data.dat

... if registered with "Vendor.Package/php-files" as the root.

I think Composer is secondary to the discussion.


-- pmj

Amy Stephen

unread,
Apr 3, 2013, 1:45:18 AM4/3/13
to php...@googlegroups.com
Paul - when I said "I disagree" is was related to your initial comment that your proposal is a deviation from PSR-0. I do not believe that is the case. I believe your proposal is still in support of PSR-0.

Yes, there are many ways to set up folders in support of PSR-0, I just shared one approach, the one I use, as an example.

Composer is amazing software that I want to use. For that reason, my approach took into account that the first two nodes come from Composer, and for that reason, I assume root to be Vendor-name/Package-name.

Thanks again.



--
You received this message because you are subscribed to a topic in the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/php-fig/JdR-g8ZxKa8/unsubscribe?hl=en.
To unsubscribe from this group and all its topics, send an email to php-fig+u...@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.

Paul Jones

unread,
Apr 3, 2013, 2:50:50 AM4/3/13
to php...@googlegroups.com

On Apr 2, 2013, at 6:45 PM, Amy Stephen wrote:

> Paul - when I said "I disagree" is was related to your initial comment that your proposal is a deviation from PSR-0. I do not believe that is the case. I believe your proposal is still in support of PSR-0.

Ah so. Even then, it doesn't appear to be the case.

PSR-0 requires a direct class-to-file mapping. For example, if a class is named "Foo\Bar\Baz\Dib", the terminating path for that class must be "Foo/Bar/Baz.php". Registering the namespace "Foo\Bar" to a path of "/path/to/package" means the class file must be located at "/path/to/package/Foo/Bar/Baz/Dib.php".

The package-oriented proposal, on the other hand, maps a registered namespace prefix to an arbitrary directory; the namespace prefix portion of the class name is stripped before converting the remainder to terminating path. Thus, registering the same namespace "Foo\Bar" to the same path of "/path/to/package" means the same class file must be located at "/path/to/package/Baz/Dib.php".


-- pmj

Hari K T

unread,
Apr 3, 2013, 3:30:45 AM4/3/13
to php...@googlegroups.com
Paul,

The good thing about the PSR-0 is you know where the file lies from the namespace .

We just want to move to the folder structure. But I like it and I don't bother any more on the folders depth , that said .

one doubt now,

I have seen people naming like

Hello.php

namespace Vendor\Package\SomeOtherNameSpaces {
    class Hello
    {
       
    }
}

If I read it correctly it will not solve this case.

So that means many people will come up with different naming conventions and next PSR.

I may be wrong also.

@Amy

It is not the problem with Man and Women saying something. Sometimes people are quite busy or they will wait for others to respond before they dive and say something. And at-times the conversation may be carried by other threads.

So don't feel bad. I at-times feel the same at some instance, but I don't care it now.

Thank you

--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.

Amy Stephen

unread,
Apr 3, 2013, 3:57:59 AM4/3/13
to php...@googlegroups.com
On Tue, Apr 2, 2013 at 7:50 PM, Paul Jones <pmjo...@gmail.com> wrote:

On Apr 2, 2013, at 6:45 PM, Amy Stephen wrote:

> Paul - when I said "I disagree" is was related to your initial comment that your proposal is a deviation from PSR-0. I do not believe that is the case. I believe your proposal is still in support of PSR-0.

Ah so.  Even then, it doesn't appear to be the case.

PSR-0 requires a direct class-to-file mapping.

Correct
 
 For example, if a class is named "Foo\Bar\Baz\Dib", the terminating path for that class must be "Foo/Bar/Baz.php".    

Assuming you mean Foo/Bar/Baz/Dib.php - if so, correct.
 
Registering the namespace "Foo\Bar" to a path of "/path/to/package" means the class file must be located at "/path/to/package/Foo/Bar/Baz/Dib.php".

Correct

 

The package-oriented proposal, on the other hand, maps a registered namespace prefix to an arbitrary directory; the namespace prefix portion of the class name is stripped before converting the remainder to terminating path.

OK. (I'm going to come back to this point - Composer creates these two folders for the Vendor/Package - I'd like to understand why you don't want to utilize that.)
 
Thus, registering the same namespace "Foo\Bar" to the same path of "/path/to/package" means the same class file must be located at "/path/to/package/Baz/Dib.php".

So -- Paul -- Your plan is skip the Vendor/Package folders altogether? How will the two different Vendor Foo/Bar packages co-exist?


My approach is very close to what you are suggesting, but it does fit PSR-0.

When Composer installs the package, it places the package into the Vendor folder, followed by the Vendor Name -- and then the package name.

    Vendor/Molajo/FieldHandler

That's why I don't include src/Vendor/Package/ in my package - that's where duplication comes from.

From that point on, the files and folders are used to complete the path.

    /Type/Alpha

The actual path (in my case, with the Class Loader hack I shared above) - is

    /Vendor/Molajo/FieldHandler/Type/Alpha.php

The PSR-0 name is:

    Molajo/FieldHandler/Type/Alpha

 Folders and Files are in 100% compliance with PSR-0, no duplication.

What is the reason for omitting Vendor/Package folders entirely from the install path?

Amy Stephen

unread,
Apr 3, 2013, 4:03:43 AM4/3/13
to php...@googlegroups.com
Thanks Hari - but the same tendencies apply to me - women are no less likely to act that way then men. =) Don't want this to go off topic because I am interested in this. Just a heads up for everyone. Nuff said.


--
You received this message because you are subscribed to a topic in the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/php-fig/JdR-g8ZxKa8/unsubscribe?hl=en.
To unsubscribe from this group and all its topics, send an email to php-fig+u...@googlegroups.com.

Amy Stephen

unread,
Apr 3, 2013, 4:37:10 AM4/3/13
to php...@googlegroups.com


On Tuesday, March 26, 2013 6:36:37 PM UTC-5, pmjones wrote:

The "src" and "tests" directories have to include vendor and package directory names. This is an artifact of PSR-0 compliance.


I know most folks are building packages this way - but this is a convention that people are following that is in no way required for PSR-0 compliance.

I believe the src folder convention is a big part of the problem. It creates three folder layers src/Vendor/Package -- unnecessarily.

If the package root is where the application files and folders are located, those three layers are gone.

The only problem that then remains is that Composer creates lowercase Vendor/Package folders. If Composer instead used the same case that the Vendor/Package requires - all extra layers would be gone.

Paul Jones

unread,
Apr 3, 2013, 5:41:11 AM4/3/13
to php...@googlegroups.com

On Apr 2, 2013, at 8:57 PM, Amy Stephen wrote:

>> For example, if a class is named "Foo\Bar\Baz\Dib", the terminating path for that class must be "Foo/Bar/Baz.php".
>
> Assuming you mean Foo/Bar/Baz/Dib.php - if so, correct.

Yeah, my bad.


>> The package-oriented proposal, on the other hand, maps a registered namespace prefix to an arbitrary directory; the namespace prefix portion of the class name is stripped before converting the remainder to terminating path.
>>
> OK. (I'm going to come back to this point - Composer creates these two folders for the Vendor/Package - I'd like to understand why you don't want to utilize that.)

The first version proposal did that; it specified two namespace names, Vendor and Package. Then Larry Garfield and others pointed out that an arbitrary number of namespaces makes it independent of any particular package manager. Thus, no dependency on any particular number of namespaces (aside from at least one, a top-level vendor name, to give broad deconfliction between projects) and no dependency on any particular package manager. I agree with Larry and the others that the arbitrary number of namespaces is the way to go.


> My approach is very close to what you are suggesting, but it does fit PSR-0.


The proposal does not replace PSR-0; it is an alternative.


> What is the reason for omitting Vendor/Package folders entirely from the install path?

For example, those who have modules with more than just source files in them can organize appropriately without duplicating the vendor/package namespace directories. For example, assuming Composer, instead of this structure under PSR-0 proper ...

vendor/
foo/
bar/
assets/
image.jpg
style.css
data/
data.csv
data.ini
src/
Foo/
Bar/
Baz.php # Foo\Bar\Baz.php
tests/
Foo/
Bar/
BazTest.php # Foo\Bar\BazTest.php


... you can have this structure under the proposed alternative:

vendor/
foo/
bar/
assets/
image.jpg
style.css
data/
data.csv
data.ini
src/
Baz.php # Foo\Bar\Baz.php
tests/
BazTest.php # Foo\Bar\BazTest.php

Note that the proposal does not require any particular kind of package organization or package manager; you can have the source files at the root if you like.


-- pmj

Hari K T

unread,
Apr 3, 2013, 5:41:54 AM4/3/13
to php...@googlegroups.com
Hi Amy,


The "src" and "tests" directories have to include vendor and package directory names. This is an artifact of PSR-0 compliance.


I know most folks are building packages this way - but this is a convention that people are following that is in no way required for PSR-0 compliance.

I believe the src folder convention is a big part of the problem. It creates three folder layers src/Vendor/Package -- unnecessarily.

No. I don't think this is an issue for it separates tests and source files.

Also it also make the docs separate etc in docs folder .

So a top level folder is good way to go.

I recall a discussion in Nette Latte templating . If you are interested https://github.com/nette/latte/issues/1
 

If the package root is where the application files and folders are located, those three layers are gone.

The only problem that then remains is that Composer creates lowercase Vendor/Package folders. If Composer instead used the same case that the Vendor/Package requires - all extra layers would be gone.

And I don't think we are trying to make it composer way . Paul already mentioned composer was just an example .
 

--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msg/php-fig/-/HKRbbAWbPaYJ.

Paul Jones

unread,
Apr 3, 2013, 5:44:14 AM4/3/13
to php...@googlegroups.com

On Apr 2, 2013, at 9:37 PM, Amy Stephen wrote:

>> The "src" and "tests" directories have to include vendor and package directory names. This is an artifact of PSR-0 compliance.
>
> I know most folks are building packages this way - but this is a convention that people are following that is in no way required for PSR-0 compliance.

The fact that they *must* include the vendor and package names as empty directories inside "src" and "tests" is required for PSR-0 compliance.


> I believe the src folder convention is a big part of the problem. It creates three folder layers src/Vendor/Package -- unnecessarily.
>
> If the package root is where the application files and folders are located, those three layers are gone.

I don't think so. You still need the (empty) Vendor and Package directories for PSR-0 compliance.


> The only problem that then remains is that Composer creates lowercase Vendor/Package folders. If Composer instead used the same case that the
> Vendor/Package requires - all extra layers would be gone.

I too wish Composer used the same case as the package, but I understand they have particular deconfliction issues that way. Regardless, we probably cannot here address the operation of Composer.


-- pmj

Amy Stephen

unread,
Apr 3, 2013, 5:50:45 AM4/3/13
to php...@googlegroups.com
On Tue, Apr 2, 2013 at 10:41 PM, Paul Jones <pmjo...@gmail.com> wrote:


The first version proposal did that; it specified two namespace names, Vendor and Package. Then Larry Garfield and others pointed out that an arbitrary number of namespaces makes it independent of any particular package manager.  

The namespace - as you and Larry are discussing - is fine.

It's the install path that collides in your example.

If I have a Molajo/Package/Foo/Bar and you have an Auro/Package/Foo/Bar, we will both install into Vendor/Foo/Bar.


 



Amy Stephen

unread,
Apr 3, 2013, 5:55:17 AM4/3/13
to php...@googlegroups.com
On Tue, Apr 2, 2013 at 10:44 PM, Paul Jones <pmjo...@gmail.com> wrote:

On Apr 2, 2013, at 9:37 PM, Amy Stephen wrote:

>> The "src" and "tests" directories have to include vendor and package directory names. This is an artifact of PSR-0 compliance.
>
> I know most folks are building packages this way - but this is a convention that people are following that is in no way required for PSR-0 compliance.

The fact that they *must* include the vendor and package names as empty directories inside "src" and "tests" is required for PSR-0 compliance.


Src, tests, doc, etc. has nothing to do with name spacing. (And it's what creates the extra folder problems.)

Its like a recommendation - but frankly, I think it's a very bad recommendation. If I understand correctly - it came out of the Log effort.

But src, tests, docs do *not* in any way, shape, or form, impact the Namespace.

Paul - please look at the way I do it very closely - look at PSR-0 - it's compliant and it does so without those extra layers.



Amy Stephen

unread,
Apr 3, 2013, 5:57:30 AM4/3/13
to php...@googlegroups.com
Aura, sorry Paul.

Amy Stephen

unread,
Apr 3, 2013, 6:00:36 AM4/3/13
to php...@googlegroups.com
Nothing on PSR-0 about the physical directory structure of your package.

https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md

Not a single word. Nada.

Paul Jones

unread,
Apr 3, 2013, 6:05:21 AM4/3/13
to php...@googlegroups.com
/me furrows brow

Per the implementation example provided, if you register them as different paths ...

$loader->add('Molajo\Package', '/path/to/molajo-package/');
$loader->add('Auro\Package', /path/to/auro-package/');

... the load() method will pull Molajo\Package\Foo\Bar from the Molajo\Package registered path, and Auro\Package\Foo\Bar from the Auro\Package registered path.

Still not sure what you're getting at here.


-- pmj

Larry Garfield

unread,
Apr 3, 2013, 6:08:50 AM4/3/13
to php...@googlegroups.com
That's only the case if you're using a single root for code from different packages.  That would indeed cause a conflict.  However, I think this "extended PSR-0" (or short-curcuited PSR-0? Whatever) would primarily be useful in cases where you're not doing that.

To reuse Paul's example from earlier:

    vendor/
        foo/
            bar/
                assets/
                    image.jpg
                    style.css
                data/
                    data.csv
                    data.ini
                src/
                    Foo/
                        Bar/
                            Baz.php # Foo\Bar\Baz.php
                tests/
                    Foo/
                        Bar/
                            BazTest.php # Foo\Bar\BazTest.php

            
... you can have this structure under the proposed alternative:

    vendor/
        foo/
            bar/
                assets/
                    image.jpg
                    style.css
                data/
                    data.csv
                    data.ini
                src/
                    Baz.php # Foo\Bar\Baz.php
                tests/
                    BazTest.php # Foo\Bar\BazTest.php


Allowing non-top-of-the-tree roots doesn't do anything for the composer-generated vendor/foo/bar/src part, but it does shorten the paths below that.  With the classes you name, you'd have:

vendor/
  /molajo
    /package
      /src
        /Foo
          /Bar.php
  /aura
    /package
      /src
        /Foo
          /Bar.php

So there's no conflict.  That said, I have a feeling that this won't be of use to free-standing libraries as much as to plugins for specific projects.  Eg, Drupal modules, Joomla plugins, etc.  As someone who works mostly in that space, though, I like the idea of making our paths shorter. :-)

--Larry Garfield

Amy Stephen

unread,
Apr 3, 2013, 6:09:12 AM4/3/13
to php...@googlegroups.com
So, you are moving away from vendor? (And I'm still confused about Composer as a side issue.)

Paul - I think you are trying to solve the same problem but throwing the baby out with the bath water. PSR-0 is fine. It's a combination of factors that create those extra folders. We could fix the problem and keep everyone on the same standard.

It's complex, hard to explain, can a few of us who are interested in this schedule a voice meeting and start with trying to get a good understanding on where these extra layers are coming from?




-- pmj

Paul Jones

unread,
Apr 3, 2013, 6:19:11 AM4/3/13
to php...@googlegroups.com

On Apr 2, 2013, at 11:09 PM, Amy Stephen wrote:

> So, you are moving away from vendor? (And I'm still confused about Composer as a side issue.)

Neither toward nor away from it. The name of the directory where the packages are stored is entirely inconsequential to the proposal.


> Paul - I think you are trying to solve the same problem but throwing the baby out with the bath water. PSR-0 is fine. It's a combination of factors that create those extra folders. We could fix the problem and keep everyone on the same standard.

Yes, I like PSR-0. It's not being thrown out. But I don't see how we can remove the directories that map to the registered namespace *and* stay within PSR-0, which requires a direct class-to-file mapping.


> It's complex, hard to explain, can a few of us who are interested in this schedule a voice meeting and start with trying to get a good understanding on where these extra layers are coming from?

You mean with me? Probably not. I hate talking by phone.

The "extra layers" are a byproduct of PSR-0 requiring a direct class-to-file mapping. The proposal allows for a mapping "past" the registered namespace prefix, so that the files in that registered namespace don't need the empty directories as placeholders. I'm not sure how many different ways it can be explained.

Besides Amy, who here is finding this "complex" and "hard to explain" ?


-- pmj

Amy Stephen

unread,
Apr 3, 2013, 6:24:07 AM4/3/13
to php...@googlegroups.com
On Tue, Apr 2, 2013 at 11:19 PM, Paul Jones <pmjo...@gmail.com> wrote:

On Apr 2, 2013, at 11:09 PM, Amy Stephen wrote:

> So, you are moving away from vendor? (And I'm still confused about Composer as a side issue.)

Neither toward nor away from it.  The name of the directory where the packages are stored is entirely inconsequential to the proposal.


> Paul - I think you are trying to solve the same problem but throwing the baby out with the bath water. PSR-0 is fine. It's a combination of factors that create those extra folders. We could fix the problem and keep everyone on the same standard.

Yes, I like PSR-0.  It's not being thrown out.  But I don't see how we can remove the directories that map to the registered namespace *and* stay within PSR-0, which requires a direct class-to-file mapping.

My install path:

Vendor / Molajo / FieldHandler / Type / Alpha.php

My namespace:
namespace Molajo\FieldHandler\Type;

My current state:
Dazed and confused.


Besides Amy, who here is finding this "complex" and "hard to explain" ?

And smiling knowing, she may be too stupid to understand or explain it too, but at least she's doing what he's hoping to accomplish. =)

Paul Jones

unread,
Apr 3, 2013, 6:35:04 AM4/3/13
to php...@googlegroups.com

On Apr 2, 2013, at 11:24 PM, Amy Stephen wrote:

>
>
> On Tue, Apr 2, 2013 at 11:19 PM, Paul Jones <pmjo...@gmail.com> wrote:
>
> On Apr 2, 2013, at 11:09 PM, Amy Stephen wrote:
>
> > So, you are moving away from vendor? (And I'm still confused about Composer as a side issue.)
>
> Neither toward nor away from it. The name of the directory where the packages are stored is entirely inconsequential to the proposal.
>
>
> > Paul - I think you are trying to solve the same problem but throwing the baby out with the bath water. PSR-0 is fine. It's a combination of factors that create those extra folders. We could fix the problem and keep everyone on the same standard.
>
> Yes, I like PSR-0. It's not being thrown out. But I don't see how we can remove the directories that map to the registered namespace *and* stay within PSR-0, which requires a direct class-to-file mapping.
>
> My install path:
>
> Vendor / Molajo / FieldHandler / Type / Alpha.php
>
> My namespace:
> namespace Molajo\FieldHandler\Type;

All righty then -- what you do with PSR-0 style autoloader is something like this:

$psr0_loader->add('Molajo\FieldHandler', '/path/to/Vendor');

And then when you ask for 'Molajo\FieldHandler\Type\Alpha' you get '/path/to/Vendor/Molajo/FieldHandler/Type/Alpha.php'.

With the proposal, you would do something like this:

$package_loader->add('Molajo\FieldHandler', '/path/to/Vendor/Molajo/FieldHandler');

And then when you ask for that same class, you get that same file.

*But*, and this is the key, the part of the directory that under PSR-0 would represent the registered namespace *can be any directory at all* and it still works. For example, your package could be structured like this:

molajo.fieldhandler/
Type/
Alpha.php

And you would register with the autoloader like this:

$package_loader->add('Molajo\FieldHandler', '/path/to/molajo.fieldhandler/');

That decouples the path for the registered namespace from being required to be identical to the namespace. Among others, folks who have very deep directory structures can benefit from this.

I don't know if that helps you or not.


-- pmj

Amy Stephen

unread,
Apr 3, 2013, 6:43:57 AM4/3/13
to php...@googlegroups.com
Paul -

I don't need help. I have it working for me. I was hoping to help you. I am 100% in compliance with PSR-0. My folders and files and my namespaces are in complete compliance. I have eliminated double folders - so the depth is never more than vendor/Molajo/Package/and/whatever/else/I/want

And, I do register like that. =)

$loader->add('Molajo\\FieldHandler', VENDOR_MOLAJO_FOLDER . '/FieldHandler');

More important than depth - is overriding your namespaced classes. I can move that sucker all over the place as I override classes. It is 100% uncoupled from the install path -- if it needs to be. Even down to the class level.

It's confusing, I know. Spent a lot of time on it, hacking code, testing with Composer and Packagist, looking at what others were doing, before I even raised the issue. Then, I documented the various issues on that gist.

It's cool - I get the problem - but I preferred to stay PSR-0 compliant. I'd personally rather everyone do so - but - I'm not a member anyway.


Paul Jones

unread,
Apr 3, 2013, 7:05:17 AM4/3/13
to php...@googlegroups.com

On Apr 2, 2013, at 11:43 PM, Amy Stephen wrote:

> I don't need help. I have it working for me. I was hoping to help you. I am 100% in compliance with PSR-0.

Then you may not find this proposal useful for you. Since it does not replace PSR-0, you should not have any trouble. Others, however, do seem to find that it cures some of their ills.


-- pmj

Larry Garfield

unread,
Apr 3, 2013, 5:03:46 PM4/3/13
to php...@googlegroups.com
Let me try a more targeted example of where this would be useful.

In Drupal 8 right now, we have a module called "serialization" that
looks like this:

/serialization
/lib
/Drupal
/serialization
/Encoder
JsonEncoder.php # \Drupal\serialization\Encoder\JsonEncoder
XmlEncoder.php # \Drupal\serialization\Encoder\JsonEncoder
/Normalizer
/ComplexDataNormalizer.php #
\Drupal\serialization\Normalizer\ComplexDataNormalizer
/SerializationBundle.php
serialization.info.yml
serialization.module

What we'd want to do instead is:

/serialization
/lib
/Encoder
JsonEncoder.php # \Drupal\serialization\Encoder\JsonEncoder
XmlEncoder.php # \Drupal\serialization\Encoder\JsonEncoder
/Normalizer
/ComplexDataNormalizer.php #
\Drupal\serialization\Normalizer\ComplexDataNormalizer
/SerializationBundle.php
serialization.info.yml
serialization.module

Drupal modules are currently *not* managed through Composer, so that is
irrelevant here.

Does that make it clearer what the benefit is?

--Larry Garfield

Phil Sturgeon

unread,
Apr 3, 2013, 5:19:18 PM4/3/13
to php...@googlegroups.com
Right on Larry, thats a good example. You don't need the word Drupal inside your own application, you know it's Drupal.

Amy: we've discussed the PSR-0 examples before and I believe they might be causing some confusion. In that previous discussion you linked to where you brought this up, you were referencing these examples like they are being used with Composer, but they aren't.

PSR-0 Examples

* `\Doctrine\Common\IsolatedClassLoader` => `/path/to/project/lib/vendor/Doctrine/Common/IsolatedClassLoader.php`
* `\Symfony\Core\Request` => `/path/to/project/lib/vendor/Symfony/Core/Request.php`
* `\Zend\Acl` => `/path/to/project/lib/vendor/Zend/Acl.php`
* `\Zend\Mail\Message` => `/path/to/project/lib/vendor/Zend/Mail/Message.php`

Same examples with Composer + PSR-0

* `\Doctrine\Common\IsolatedClassLoader` => `/path/to/project/lib/vendor/doctine/common/src/Doctrine/Common/IsolatedClassLoader.php`
* `\Symfony\Core\Request` => `/path/to/project/lib/vendor/symfony/core/src/Symfony/Core/Request.php`
* `\Zend\Acl` => `/path/to/project/lib/vendor/zend/framework/src/Zend/Acl.php`
* `\Zend\Mail\Message` => `/path/to/project/lib/vendor/zend/framework/src/Zend/Mail/Message.php`

Pauls Proposition

* `\Doctrine\Common\IsolatedClassLoader` => `/path/to/project/lib/vendor/doctine/common/src/IsolatedClassLoader.php`
* `\Symfony\Core\Request` => `/path/to/project/lib/vendor/symfony/core/src/Request.php`

Notice how that secondary two-layers of folder structure is now removed. 

The reason this is an alternative to PSR-0 is because some packages do not match identically their vendor/package name. For this example I'm sticking with Zend, who may or may not do this but its how Laravel does it and so do plenty of others.

* `\Zend\Acl` => `/path/to/project/lib/vendor/zend/framework/src/Zend/Acl.php`
* `\Zend\Mail\Message` => `/path/to/project/lib/vendor/zend/framework/src/Zend/Mail/Message.php`

Notice how zend/framework != Zend/Acl or Zend\Mail? That means this new autoloader would never work with them. But, that is ok. That's why having both seems to me like a great idea. To the outside user its identical, to the package developer they can chose to skip this folder structure if they follow a few careful rules about how they name their package. win win, right?

The src/ folder

I've noticed you saying a few times we should kill the src/ folder convention, but thats not really anything to do with the autoloaders we're discussing. That's just a convention that people happen to use and is up to the package developer. They can use it or not, but its nice that it works and its definitely a strong convention, as for example both Laravel and PyroCMS packages have all sorts of things outside of the src/ folder. tests/, assets/, docs/ whatever, and that should not all be accessible by the autoloader. It wouldnt be autoloadable anyway, but making the clear definition just makes sense. Even other PHP files in PyroCMS for example should not even be attempted to be autoloaded (the CodeIgniter controllers) while we have a src/ folder which should be autoloaded. The separation is nice, and logical.

Beau Simensen

unread,
Apr 3, 2013, 5:27:38 PM4/3/13
to php...@googlegroups.com
On Wednesday, April 3, 2013 10:03:46 AM UTC-5, Larry Garfield wrote:
Does that make it clearer what the benefit is?

It was always clear to me what the benefit was at the package author level. I think a lot of people would be excited to be able to optionally remove the namespace prefix from the filesystem itself.

I'm on the fence as a user, though, as the benefit of knowing exactly where to find the class is in PSR-0 is pretty nice. I was just starting to get used to having some consistency and being able to easily find the file in which a class is defined. If I have to start trying to guess (or just know from experience) if the file is going to be lib/ArrayCollection.php, lib/Collections/ArrayCollection.php, lib/Common/Collections/ArrayCollection.php or lib/Doctrine/Common/Collections/ArrayCollection.php it is going to make me a little unhappy.

I get the feeling that this is an uphill battle, though. Between subtree splits and anyone else using target-dir, this is already starting to happen. On the upside, Composer currently expands target-dir so that you can always expect to find the full namespace prefix even if the package author gets to work on the package directly without it. The only hard thing now is knowing which package ( doctrine/common or doctrine/collections ) I need to start in but at least in that case I probably know which packages I'm including in the project I'm working on.

Paul Jones

unread,
Apr 3, 2013, 5:42:31 PM4/3/13
to php...@googlegroups.com

On Apr 3, 2013, at 10:27 AM, Beau Simensen wrote:

> the benefit of knowing exactly where to find the class is in PSR-0 is pretty nice. I was just starting to get used to having some consistency and being able to easily find the file in which a class is defined. If I have to start trying to guess (or just know from experience) if the file is going to be lib/ArrayCollection.php, lib/Collections/ArrayCollection.php, lib/Common/Collections/ArrayCollection.php or lib/Doctrine/Common/Collections/ArrayCollection.php it is going to make me a little unhappy.

Man, I *totally* hear you on this. That's my single favorite thing about PSR-0. But as with economics, there are no solutions, only tradeoffs; the suggested proposal loses the 100% consistency in favor of (1) recognizing common practices and (2) shallower package structures.


-- pmj

Amy Stephen

unread,
Apr 3, 2013, 7:09:34 PM4/3/13
to php...@googlegroups.com
Larry -

That helps A LOT. Now, you are talking about your project-specific code (not just core, but also your community contributed modules) -- in other words code outside of the vendor space.

IMO - PSR-0 doesn't cover that and it's also not an issue for standard Composer installs, either, since Composer uses the Vendor folder for it's standard installs.

For Molajo, I didn't include the Vendor-name/Package-name approach for these files.  These files will never be packages -- you'll only use them with Molajo. Here's an example:

https://github.com/Molajo/Standard/blob/master/Extension/Theme/Foundation/Plugin/Foundation/FoundationPlugin.php#L7

Namespace:
   Extension\Theme\Foundation\Plugin\Foundation;

Now - my approach is flimsy at best. It could create problems if there is an Extension vendor (or a Sites vendor) which provides a like-named plugin at the same level. So, it's certainly not fool proof.

If anything, we are MISSING a standard for what should be done for those folders and files that will not be offered as packages. If you want to address that gap, good.

But anything that will be shared as a package that would be installed into the Vendor folder should follow PSR-0, IMO.

Thanks, Larry. Appreciate that clarity.




--Larry Garfield

--
You received this message because you are subscribed to a topic in the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/php-fig/JdR-g8ZxKa8/unsubscribe?hl=en.
To unsubscribe from this group and all its topics, send an email to php-fig+unsubscribe@googlegroups.com.

Amy Stephen

unread,
Apr 3, 2013, 7:17:43 PM4/3/13
to php...@googlegroups.com
On Wed, Apr 3, 2013 at 10:19 AM, Phil Sturgeon <em...@philsturgeon.co.uk> wrote:
 
and I believe they might be causing some confusion. In that previous discussion you linked to where you brought this up, you were referencing these examples like they are being used with Composer, but they aren't.

 


The src/ folder

I've noticed you saying a few times we should kill the src/ folder convention, but thats not really anything to do with the autoloaders we're discussing.

Please take 5 or 10 minutes to read my gist.  See if you still believe I don't understand these things.

https://gist.github.com/AmyStephen/4756621

 
That's just a convention that people happen to use

Right - that's why I told Paul it's not part of PSR-0.
 
 

Beau Simensen

unread,
Apr 3, 2013, 8:44:35 PM4/3/13
to php...@googlegroups.com
On Tuesday, April 2, 2013 11:43:57 PM UTC-5, Amy Stephen wrote:
It's cool - I get the problem - but I preferred to stay PSR-0 compliant. I'd personally rather everyone do so - but - I'm not a member anyway.

Hi Amy!

I wasn't able to jump in last night so I may have missed the boat, but some of what you wrote made makes it clear that you feel pretty strongly that a lot of people, Composer included, are not PSR-0 compliant. So I tried to read PSR-0 with a fresh set of eyes.

I've also read your gist and I've read most (all?) of your arguments. You clearly have a good handle on what you want to do based on your understanding of PSR-0. I want to think I'm starting to better understand where you are coming from, especially after having taken another look at PSR-0. I'm probably not, though. :)

I may be mixing up some of your signals, though. So if you've changed your stance on some of these things, it is possible I missed it, read something out of order, or straight up misinterpreted something. :)


I think that the problem is in how PSR-0 can be interpreted based on the [Examples][1] and the [Example Implementation][2] in the document. I think the [SplClassLoader][3] is far better at revealing the intention of the PSR-0 authors, but I can see how one might interpret that all classes need to live beside each other (in vendor/ or otherwise) just based on the other two example sections.

I do not believe it was ever the intention of the PSR-0 authors for all of the classes to live under the same PSR-0 root. This seems to be how you've interpreted it, though? From some of the things you've written it sounds like you believe that in order to be "100% PSR-0 Compliant" the following should be required and you've personally gone to great lengths to make this possible for some of your packages:

 * vendor/Doctrine/Common/Collections/ArrayCollection.php
 * vendor/Symfony/Component/HttpFoundation/Request.php

Would I be correct in making that statement?

If so, based on the examples in the PSR-0 document itself, I can see how someone might come to that conclusion. I can also see how someone would then look at Composer's implementation ( vendor/<vendor>/<package>/src/<Vendor>/<Package>/Foo.php ) and see it as not strictly following PSR-0 and want to fight pretty hard for it to be vendor/<Vendor>/<Package>/Foo.php in order to make it PSR-0 compliant.

I don't think there is anything wrong with this interpretation of PSR-0 at all. I think that implementing a package manager to dump all of the code into one big vendor folder is as PSR-0 compliant as Composer's current solution is. I don't think I've ever seen an attempt to bring all of a project's external dependencies under a single PSR-0 root like vendor/, though. At least not until now? It sounds like maybe that is what you've accomplished?

In the end it is an implementation detail to me and I don't really care as long as my classes load correctly. If Composer had a switch tomorrow to let me toggle between the two, I probably wouldn't switch it. If the new default behavior was to aggregate everything into vendor/ like you are suggesting, I probably wouldn't care enough to switch back to the old functionality.

As for another way that PSR-0 can be interpreted, most (all?) of the generic PSR-0 class loaders that I have seen (Composer included) require both a namespace and a path to define the PSR-0 mapping. These are largely based on the ideas put forth by the the [SplClassLoader example implementation][4] linked from the PSR-0 document. I think it might be a better indicator of how the original authors intended for PSR-0 to be interpreted. Specifically, from the example at the top:

* // Example which loads classes for the Doctrine Common package in the
* // Doctrine\Common namespace.
* $classLoader = new SplClassLoader('Doctrine\Common', '/path/to/doctrine');
* $classLoader->register();


It does not say '/path/to/vendor', or '/path/to/all/dependencies/in/the/same/directory', it says, '/path/to/doctrine'. The reason that a namespace and a path are both required is because each namespace prefix is assumed to potentially be in its own directory. In the case of external dependencies they need to be kept separate so that they do not clobber each other. A lot of the reasons for this were practical. Back in the good old days (after PSR-0 but before Composer) people would end up doing things like this manually:

mkdir vendor
cd vendor
git clone g...@github.com:doctrine/common.git doctrine-common
git clone g...@github.com:symfony/HttpFoundation.git symfony-http-foundation

And then something like this:

$classLoader->add('Doctrine\\Common', 'vendor/doctrine-common/lib');
$classLoader->add('Symfony\\Component\\HttpFoundation', 'vendor/symfony-foundation');


What Composer brought to the table was a way to automate the above listed steps for everyone and basically turn vendor/ into a blackbox that everyone could use in exactly the same way: require vendor/autoload.php.

In the process, Composer had to find a way to ensure that different projects will never collide with each other. Manually I can rewrite the clone output to be "doctrine-common" instead of "common" and "symfony-http-foundation" instead of "HttpFoundation." Composer decided to ensure uniqueness by requiring a unique package name that included a vendor. This prevented someone from writing a "cache" package that could secure the prime "vendor/cache" directory. That is why we can now safely each publish our own cache package under our vendor resulting in "vendor/doctrine/cache" and "vendor/symfony/cache" and "vendor/gir/cache". No one cache package will clobber any other cache package.

The main problem I'm seeing now is that not everyone thinks of vendor/ as a black box like I do. :) I'm also starting to see that people are looking at this as Composer in some way not being PSR-0 compliant? This is definitely not the case and I think these are things that need to be addressed. I just don't think that the PSR-0 or PSR-X need to play any part in it.

In any event, I don't see your implementation as being wrong. I think that the implications that other interpretations are not right is wrong, though. :) Your preferred directory layout under vendor/ being incompatible with how Composer handles it does not make Composer's implementation of PSR-0 incorrectly. It just makes it different.

The fact that there is more than one considerably different interpretation at all is a problem. I think this is the spec's fault for not being more clear. It references a vendor/ directory in all of its examples but it does not make it clear that the vendor/ directory itself is not a part of the spec. It also should have been more varied to ensure that someone reading the examples would know that the namespaces can all live in different locations and are not expected to be found in a single directory root.

I think that the SplClassLoader implementation shows more clearly what the PSR-0 authors intended with how external project dependencies CAN be handled. Mainly, the SplClassLoader implementation introduces the path / namespace prefix pair concept that is not discussed anywhere in the PSR-0 document itself.

But again, these are implementation details. It is perfectly valid to aggregate all of your external dependencies under a single PSR-0 root. I just don't know that Composer will ever be able to do that directly. This does not in any way make Composer less PSR-0 compliant.


It's complex, hard to explain, can a few of us who are interested in this schedule a voice meeting and start with trying to get a good understanding on where these extra layers are coming from?

I'm not one for voicecomms but clearly I'm interested in working through this with people. An IRC chat or some other form of group chat might be nice to talk through some of these issues.

I'd really like to understand workflows that require people to work in vendor/. Maybe there are other solutions that would work better? Working in vendor/ is no fun for a lot of reasons. I'll be the first to admit that. It is why I've worked hard to find alternatives to having to do so and largely try to ignore vendor/ altogether. One of [my earliest pull requests ever][5] was to Composer to try and help working with dev dependencies because working in vendor/ is icky. Though that PR was not successful, I have [continued to try and make things easier for working with Composer][6] when it comes to dev dependencies.

Maybe we can come up with some solutions that will make working in vendor/ easier? Maybe in some cases we can work around doing things in vendor/ entirely. I'd have a lot of questions and I think it would be easier to ask in another forum or at the very least another thread.

My schedule is whacky so it is possible I will not be able to join, but if it is scheduled I'll do my best to make it if I can. :)



Beau Simensen

unread,
Apr 3, 2013, 8:48:07 PM4/3/13
to php...@googlegroups.com
On Wednesday, April 3, 2013 10:19:18 AM UTC-5, Phil Sturgeon wrote:
* `\Zend\Acl` => `/path/to/project/lib/vendor/zend/framework/src/Zend/Acl.php`
* `\Zend\Mail\Message` => `/path/to/project/lib/vendor/zend/framework/src/Zend/Mail/Message.php`

Notice how zend/framework != Zend/Acl or Zend\Mail? That means this new autoloader would never work with them. But, that is ok. That's why having both seems to me like a great idea. To the outside user its identical, to the package developer they can chose to skip this folder structure if they follow a few careful rules about how they name their package. win win, right?

This is an important point. Sometimes the second level namespace has nothing to do with the whole package itself. For example, my dflydev/doctrine-orm-service-provider package has the following namespaces in it:

 * Dflydev\Pimple\Provider\DoctrineOrm
 * Dflydev\Silex\Provider\DoctrineOrm
 * Dflydev\Cilex\Provider\DoctrineOrm

I don't see a world where I can create a descriptive Composer package name and still have the directory structure I want if the Composer package name has anything to do with the namespace.

I could of course do something like this:

 * Dflydev\DoctrineOrmServiceProvider\Pimple
 * Dflydev\DoctrineOrmServiceProvider\Silex
 * Dflydev\DoctrineOrmServiceProvider\Cilex

Some could argue this is a better namespace organization anyway, but the point is I have a choice now. If the Composer package name had to match the second level namespace I'd no longer have a choice.

Amy Stephen

unread,
Apr 3, 2013, 9:31:43 PM4/3/13
to php...@googlegroups.com
On Wed, Apr 3, 2013 at 1:44 PM, Beau Simensen <sime...@gmail.com> wrote:
On Tuesday, April 2, 2013 11:43:57 PM UTC-5, Amy Stephen wrote:
It's cool - I get the problem - but I preferred to stay PSR-0 compliant. I'd personally rather everyone do so - but - I'm not a member anyway.

Hi Amy!

I wasn't able to jump in last night so I may have missed the boat, but some of what you wrote made makes it clear that you feel pretty strongly that a lot of people, Composer included, are not PSR-0 compliant. So I tried to read PSR-0 with a fresh set of eyes.

Composer is *perfectly* PSR-0 compliant.  It just adds a couple of extra folders I could do without.

I don't know where "a lot of people" comes from, everything I have reviewed is PSR-0 compliant. 

No, I don't make any assumptions that the name space must be in Vendor to be PSR-0 compliant, either. 

But, remember, my gist is about the *combination* of these things:

1. PSR-0
2. Using Composer/Packagist
3. The folder structure you use when you store your package.

That's where Vendor comes into it since Composer installs there. (No, it's not part of PSR-0, yes, it does matter if you use Composer.)

My gist is intended for those of us who want nice, simple install paths like:

    Vendor/Molajo/Filesystem/Type/Ftp.php

to implement a namespace like:

    Molajo\Filesystem\Type\Ftp.

In addition to what is on the gist, I hacked the Composer Classloader a bit - link above somewhere. (I can share it again if you need it.) 

One more point (and in all honesty, I am going to have to spend more time with your note) - on this comment:


Beau said:

This is an important point. Sometimes the second level namespace has nothing to do with the whole package itself. For example, my dflydev/doctrine-orm-service-
provider package has the following namespaces in it:

<snip>

I don't see a world where I can create a descriptive Composer package name and still have the directory structure I want if the Composer package name has anything to do with the namespace.


Both Composer and Packagist say that the first two values are *supposed to be* PSR-0 compliant, and as such, should represent your Vendor-name/Package-name portion of the namespace.

https://packagist.org/about

Don't have time right now to dig around the composer doc to find that statement, will later.

Again - there are lots of factors at play. Some parts are the standard, other the tools we share, others are convention. I tried to sort thru where choices impact the length of the install path for those who care about short paths and still want to stay compliant.

Beau - does that help clear up my point?

Amy Stephen

unread,
Apr 3, 2013, 9:42:53 PM4/3/13
to php...@googlegroups.com
Beau -

OK, again on your question about composer Vendor-name/Package-name

The Packagist site indicates you must use the Vendor-name/Package-name for your listing.

https://packagist.org/about

The way this impacts Composer is via the matching process (duh)

https://getcomposer.org/doc/02-libraries.md#publishing-to-a-vcs

So, that's how that ties together and why I say you can rely on those two nodes to serve as PSR-0 's first two nodes. If you are following the instructions to list on Packagist, then that's exactly what you are required to do.

Beau Simensen

unread,
Apr 3, 2013, 11:01:14 PM4/3/13
to php...@googlegroups.com


On Wednesday, April 3, 2013 2:31:43 PM UTC-5, Amy Stephen wrote:
Composer is *perfectly* PSR-0 compliant.  It just adds a couple of extra folders I could do without.
I don't know where "a lot of people" comes from, everything I have reviewed is PSR-0 compliant.  

It is entirely possible I was reading too much into this. I could find quotes that led me to believe this but I guess it doesn't matter. They were probably in reference to some other aspect of the overall problem and I simply misunderstood. =)

 
No, I don't make any assumptions that the name space must be in Vendor to be PSR-0 compliant, either.  

Sorry if I gave that impression. It was clear to me that you think code within your actual project can still be PSR-0 compliant even without being in vendor. But it did sound to me like you were under the impression that code in vendor/ needed to be structured a certain way to be considered PSR_0 compliant. I am getting that I was wrong on this so I'll drop it for now, though. :)


Both Composer and Packagist say that the first two values are *supposed to be* PSR-0 compliant, and as such, should represent your Vendor-name/Package-name portion of the namespace.

This kind of shocked me. If it was true I'd be in for a world of hurt. :) I had to look it up to see for myself to be sure. I think this is another case of multiple interpretations of the same text.

From the Packagist about page linked above (emphasis mine):

The most important part is that the first bit of the package name must be the vendor name, suffixed by a forward slash (/). This follows the PSR-0 standard for namespaces naming.

My interpretation of this is that only that a vendor name must be included in the package's name. It then references PSR-0 as in, "like you need to have for a PSR-0 namespace," not as in, "the vendor name you choose should match the PSR-0 vendor name in your project's namespace."

It is completely silent on the rules governing the Package-name portion of the package's name. Even PSR-0 is silent on this so I do not see any link at all between the Package-name portion and any subsequent namespaces below the vendor.

It does show several examples, though, including "monolog/monolog-drupal-module," which I think fits pretty closely to my example. It is possible that "monolog-drupal-module" will more or less translate to Monolog/Drupal/Module namespace, but it could also be anything else. There is no way of knowing because there is no relationship between the Composer package name and the actual namespace.

The Composer docs don't mention anything about a 1:1 mapping either. They don't even mention PSR-0.


The package name consists of a vendor name and the project's name. Often these will be identical - the vendor name just exists to prevent naming clashes. It allows two different people to create a library named json, which would then just be named igorw/json and seldaek/json.
 
Here we are requiring monolog/monolog, so the vendor name is the same as the project's name. For projects with a unique name this is recommended. It also allows adding more related projects under the same namespace later on. If you are maintaining a library, this would make it really easy to split it up into smaller decoupled parts.

So I do not think it is true that there is a 1:1 mapping between the Composer package name and any namespaces. If there are other parts of the documentation (either for Composer or for Packagist) that contradict this we should definitely clean that up because unless Jordi or Nils says otherwise, I do not think that the intention was ever to have a 1:1 map between a Composer package name and any part of a PSR-0 compatible namespace. In fact, if there are parts that even imply this we should address that. Like maybe the packagist/about page needs to be changed to not even reference PSR-0.


 
Again - there are lots of factors at play. Some parts are the standard, other the tools we share, others are convention. I tried to sort thru where choices impact the length of the install path for those who care about short paths and still want to stay compliant.
 
Beau - does that help clear up my point? 

Some, yes. Sometimes it is hard to see everything when things are coming from several angles. :) Thanks for following up!

I've said it a few times, hoping someone would bite but nobody has. I still want to talk to the people who "care about short paths", especially when it comes to Composer's vendor/ directory, and find out how we can help that out besides changing how Composer installs things. I really don't think that tweaking Composer's install paths is the only answer.

I don't know if fig is a good place to have this discussion, though... I'm open to suggestions if people are interested in discussing this outside of this thread?

Jordi Boggiano

unread,
Apr 3, 2013, 11:25:11 PM4/3/13
to php...@googlegroups.com
> So I do not think it is true that there is a 1:1 mapping between the
> Composer package name and any namespaces. If there are other parts of
> the documentation (either for Composer or for Packagist) that contradict
> this we should definitely clean that up because unless Jordi or Nils
> says otherwise, I do not think that the intention was ever to have a 1:1
> map between a Composer package name and any part of a PSR-0 compatible
> namespace. In fact, if there are parts that even /imply/ this we should
> address that. Like maybe the packagist/about page needs to be changed to
> not even reference PSR-0.

Ack, it should be changed. I never realized because this was written
ages ago and never looked at again, but I guess this is what has been
confusing a few people into thinking their package vendor name must be
the same as in the code. Please PR :)

Cheers

--
Jordi Boggiano
@seldaek - http://nelm.io/jordi

Amy Stephen

unread,
Apr 3, 2013, 11:55:07 PM4/3/13
to php...@googlegroups.com
Going to have to have Beau change that, not sure what it should be - thanks Jordi.

Regardless - if you *do* use those two as your PSR-0 Vendor-name/Package-name -- you have the first two nodes for your namespace.

I like it like that.


OK - Beau - with Jordi's post, we're square, right?

The only comment I have made about PSR-0 compliance is in *this* thread - would prefer to see everything in the Vendor folder follow the same rules - rather than come up with a new approach.

Let's get back on topic for Paul's and Larry's approach. Larry gave an example of Drupal code that will never be a shared package and how to handle namespacing there.

It's my opinion that PSR-0's scope is *shared packages* (typically) installed into the Vendor folder.

So, what's done outside of that space, IMO, is up to the project and has not yet been defined.


--
You received this message because you are subscribed to a topic in the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/php-fig/JdR-g8ZxKa8/unsubscribe?hl=en.
To unsubscribe from this group and all its topics, send an email to php-fig+u...@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.

Amy Stephen

unread,
Apr 4, 2013, 12:38:03 AM4/4/13
to php...@googlegroups.com
OK. Looks like there is a formal proposal - https://groups.google.com/forum/?hl=en#!topic/php-fig/qT7mEy0RIuI

Probably better for those who wish to discuss do so there.

Phil Sturgeon

unread,
Apr 4, 2013, 1:54:50 PM4/4/13
to php...@googlegroups.com
Amy: I'm glad you linked me to that gist, it shows off a much better understanding than you've ben demonstrating throughout this conversation so I think we're closer to being on the same page. I think Beau has nailed it though, Composer does vendor/package because Composer itself wants to keep the file-system from clashing and vendor/package has nothing whatsoever to do with PSR-0.

Composer is PSR-0 compatible, but that doesnt mean that all folders inside composers vendor/ folder need to be entirely PSR-0, more that there are multiple PSR-0 routes available and the PSR0Vendor\PSR0Package  names are then available to push the autoloader to the correct PSR-0 route. This is important because not all Composer packages are PSR-0, many are just sitemap, so Composer cannot make such assumptions about everything inside being PSR-0.

 If Composer did not use the same value for name twice in the path;

It's not the same value, just sometimes it happens to be. They are often totally different things.

 If the Composer name values were allowed in mixed case and then could be used as part of the namespace;

Composer doesnt need to change that, but this new autoloader could do some guesswork to try it out.

Do not add folders to the "top" of your package repository that are not a part of your namespace.

This suggests you think having src/ in there breaks PSR-0 compatibility, which my thoughts that you think everything under vendor/ should be PSR-0, which again would break the fundamental usage of Composer.

I've said before (and Beau agrees) that the PSR-0 example is confusing, especially with the use of vendor/ in there. Maybe we can change that, but Composer and PSR-0 are not the same thing. Composer is perfectly PSR-0 compatible and PSR-0 is by design a little verbose, this new autoloader will hopefully solve some of the problems you've been having with the double-folder structure without having to change Composer or PSR-0, which are both doing their jobs perfectly. You could comment on my walk through of the examples as I feel like you skipped most of my response with your answer.

Let's get back on topic for Paul's and Larry's approach. Larry gave an example of Drupal code that will never be a shared package and how to handle namespacing there. 
It's my opinion that PSR-0's scope is *shared packages* (typically) installed into the Vendor folder. 

PSR-0 does not require a vendor folder (or any name) at all. The fact that the example has one, and composer happen to use one, is probably just a total coincidence, or they are both used because its a common place to put stuff. FuelPHP had a vendor/ folder too, which was nothing to do with either Composer or PSR-0 - so I guess it could be just a good name. This example like I've said to you a few times is confusing, and should probably be changed.

I mentioned above about how each installed Composer package adds a "PSR-0 Root" to look through, and the Namespaces held "route" the include to the correct folder structure (the correct "PSR-0 Root". Well as well as Composer packages your entire application can have PSR-0 roots anywhere you please. I enable a PSR-0 root inside each PyroCMS module:

        // Lets PSR-0 up our modules
        $loader = new \Composer\Autoload\ClassLoader;
        foreach ($modules as $module) {
            // register classes with namespaces
            $loader->add('Pyro\\Module\\'.ucfirst($module['slug']), $module['path'].'/src/');
        }

So this is a path to a valid PSR-0 root:

system/cms/modules/users/src/

That is not composer at all, but it works in the exact same way.

Pyro\Module\Users\Model\Group.php => system/cms/modules/users/src/Pyro/Module/Users/Model/Group.php

No vendor anywhere in sight, I have top level folders in my "package" and it's still all perfectly PSR-0.

What im trying to explain is that PSR-0 was never wrong, or incompatible because PSR-0 is used for so many different things in different ways. The packagist names and namespace name have no connection to each other at all nor should there be any requirement that they do. BUT a new autoloader could definitely be made to take advantage of a naming convention of these packages to translate some of it into the first two levels of the namespace.

Putting this logic into PSR-0 would infect and taint the standard. Making another autoloader specifically to work with packages like this would be very handy, for those that can use it - which won't be all by any means.

Jason Judge

unread,
Apr 4, 2013, 2:45:21 PM4/4/13
to php...@googlegroups.com
tl;dr version: PSR-0 deals with the directory structure that matches the namespace and name of a class. What sits outside the root of that directory structure, and where that directory structure is located, and how many structures there are in a project, is not mentioned or specified by, or anything to do with PSR-0.

That's how I have always seen it, and hopefully that is correct, but I can see how confusion can creep in, especially with the examples given. Composer kind of pulls in so much functionality, concepts and directory structures of its own, that it is often difficult to peel apart the layers to see just which bit of it implement and *is* PSR-0.

-- Jason

Beau Simensen

unread,
Apr 5, 2013, 4:16:54 AM4/5/13
to php...@googlegroups.com, amyst...@gmail.com
On Wednesday, April 3, 2013 4:55:07 PM UTC-5, Amy Stephen wrote:
Going to have to have Beau change that, not sure what it should be - thanks Jordi.
 
For what it is worth, the PR against the Packagist about page was merged earlier today. There is no more mention of PSR-0 on the Packagist about page in relation to Composer package names.

https://github.com/composer/packagist/pull/304
Reply all
Reply to author
Forward
0 new messages