Proposal: Package-Oriented Autoloader

1,179 views
Skip to first unread message

Paul Jones

unread,
Apr 3, 2013, 12:47:23 PM4/3/13
to php...@googlegroups.com
Greetings all,

N.b.: If this proposal is adopted, PSR-1 MUST be be amended so that the requirement to follow PSR-0 becomes a requirement to follow either PSR-0 or this proposal.

Let the beatings commence!

* * *


Package-Oriented Autoloader
===========================

Introduction
------------

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.

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.

However, with the recent proliferation of packages, modules, and bundles in PHP, we note that conforming to the PSR-0 standard leads to deeper empty directory structures in distributions, like the following:

Foo_Bar_Package/
src/
Foo/
Bar/
Baz.php # Foo\Bar\Baz
tests/
Foo/
Bar/
BazTest.php # Foo\Bar\BazTest

The behavior has been noted as problematic:

- <https://igor.io/2013/01/23/autoload-insanity.html>
- <https://groups.google.com/d/msg/php-fig/-BPdegzme_Y/ZVR_4gVMoIkJ>

This proposal seeks to provide an *alternative to* (not a *replacement for*) PSR-0 that allows for a structure that makes the directory structures less deep, like the following:

Foo_Bar_Package/
src/
Baz.php # Foo\Bar\Baz
tests/
BazTest.php # Foo\Bar\BazTest

Additionally, since the use of underscores in class names was to represent pseudo-namespaces in PHP 4 to PHP 5.2.x, their use when namespaces proper are available is no longer necessary. This removes possible conflicts between `Foo\Bar` and `Foo_Bar`.


Rules
-----

(The term "class" below refers to classes, interfaces, and traits.)

- Fully-qualified class names MUST begin with a top-level namespace name, which MUST be followed by zero or more sub-namespace names, and MUST end in a class name.

- Class files MUST contain only one class definition.

- Autoloader implementations MUST map a namespace prefix to a directory.

- Autoloader implementations MUST allow each namespace prefix to be mapped to multiple directories.

- Autoloader implementations MUST map the non-namespace-prefix portion of the fully-qualified class name to a sub-path by replacing namespace separators with directory separators, and MUST suffix the result with `.php`.

- Autoloader implementations MUST search for class files among their registered namespace prefixes in a depth-first fashion.

- Autoloader implementations MUST search the paths for a registered namespace in the order those paths were registered.


Narrative
---------

Given the below example implementation, and a `Foo\Bar` package of classes, one would register the path to "source" files and "unit test" files for the namespace prefix like so:

// instantiate the loader
$loader = new PackageOrientedLoader;

// register the source file paths for the namespace prefix
$loader->addNamespacePath(
'Foo\Bar',
'/path/to/Foo.Bar/src'
);

// register the unit test paths for the namespace prefix
$loader->addNamespacePath(
'Foo\Bar',
'/path/to/Foo.Bar/tests'
);

Given a package in a "sub-namespace" of `Foo\Bar\Baz\Dib`, one would register the "sub-package" like so:

$loader->addNamespacePath(
'Foo\Bar\Baz\Dib',
'/path/to/Foo.Bar.Baz.Dib/src'
);

When the autoloader calls `load()` for a fully-qualified class name of `Foo\Bar\Baz\Dib\Zim\Gir`, the implementation will search the registered paths in this order:

- first, for `/path/to/Foo.Bar.Baz.Dib/src/Zim/Gir.php`;
- then, for `/path/to/Foo.Bar/src/Baz/Dib/Zim/Gir.php`;
- last, for `/path/to/Foo.Bar/test/Baz/Dib/Zim/Gir.php`;

Note that the longest registered namespace prefix that matches the fully-qualified class name is searched first, and the shortest is searched second. When a registered namespace prefix has multiple paths, the paths are searched in the order they were registered.


Example Implementation
----------------------

The following is one possible implementation of the rules described above.

<?php
/**
* An example implementation for a package-oriented autoloader.
*/
class PackageOrientedAutoloader
{
/**
*
* An array where the key is a namespace prefix, and the value is a
* sequential array of directories for classes in that namespace.
*
* @var array
*
*/
protected $paths = array();

/**
*
* Adds a path for a namespace prefix.
*
* @param string $ns The namespace prefix.
*
* @param string $path The directory containing classes in that
* namespace.
*
* @return void
*
*/
public function addNamespacePath($ns, $path)
{
$path = rtrim($path, DIRECTORY_SEPARATOR);
$this->paths[$ns][] = $path;
}

/**
*
* Loads the class file for a fully qualified class name.
*
* @param string $fqcn The 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;
}

/**
*
* Uses `require` to read a file from the filesystem.
*
* @param string $file
*
* @return bool True if the file gets read; false if it does not.
*/
protected function readFile($file)
{
if (! is_readable($file)) {
return false;
}

require $file;
return true;
}
}

* * *


-- pmj

Jordi Boggiano

unread,
Apr 3, 2013, 12:58:13 PM4/3/13
to php...@googlegroups.com
Heya,

> Let the beatings commence!

As far as I'm concerned, thou shalt live to see another day. No big
issues with the proposal. I fear the main contention point is gonna be
how do we amend PSR-1 ;)
I think PSRs should avoid linking to external resources as much as
possible, because URLs are not forever.

Cheers

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

Donald Gilbert

unread,
Apr 3, 2013, 5:26:09 PM4/3/13
to php...@googlegroups.com
Very good proposal indeed. 

I only have one point of contention: 
- Autoloader implementations MUST search the paths for a registered namespace in the order those paths were registered. 

IMO, Namespaces need to be searched in LIFO order. This makes overriding classes a simple task, which would be useful for fixing problems in 3rd party libraries when needed as well as potentially mocking out classes during testing.

Jordi Boggiano

unread,
Apr 3, 2013, 5:32:34 PM4/3/13
to php...@googlegroups.com
Just a note on that, the composer autoloader has a $prepend flag on the
add() method, so you can add a new mapping and if it must override set
it to be prepended.

I find it more natural to keep the FIFO order, because that's how
spl_autoload_register works for example.

Donald Gilbert

unread,
Apr 3, 2013, 5:40:45 PM4/3/13
to php...@googlegroups.com
That's right, I hadn't made that connection but it makes sense.

It should be noted then that any implementation of this new autoloader should allow for that as well.
Message has been deleted

Paul Jones

unread,
Apr 3, 2013, 6:37:18 PM4/3/13
to php...@googlegroups.com

On Apr 3, 2013, at 5:16 PM, Amy Stephen wrote:

> So - now we can amend PSRs?

Not yet we can't, which is why I wanted to bring it up early.

The issue is that PSR-1 states you must comply with PSR-0 to be PSR-1 compliant. Obviously we don't want adopters of this proposal (should it pass) to find themselves out of compliance. So we need to do one of the following:

- modify PSR-0 to say that complying with this proposal (if accepted) is a sufficient alternative

- modify PSR-1 to say "comply with PSR-0 +++or PSR-N+++"

- modify this proposal to state that complying with it is sufficient to meet the requirement of complying with PSR-0 for the purposes of PSR-1

Thoughts, anyone?


-- pmj

Evert Pot

unread,
Apr 3, 2013, 6:51:42 PM4/3/13
to php...@googlegroups.com
In the IETF world, it's completely fine to amend, clarify or change the meaning of older RFC's.
I think this is the proper way to go about it. Once PSR's are made, they should be set in stone.

Evert

Amy Stephen

unread,
Apr 3, 2013, 7:40:20 PM4/3/13
to php...@googlegroups.com
Paul -

I'm not a member, so, not sure if I am out of line now commenting or not.

I still hope that the issues can be resolved without a new standard. I believe a second namespacing standard will do nothing but confuse people and slow adoption.

There is a combination of issues at play:

1. PSR-0 Scope

It is my opinion that PSR-0 only applies to packages intended for sharing between projects. The standard talks about "libraries" and specifically mentions "interoperability."

Larry raised the issue of Drupal namespacing -- outside of that scope -- and it is my opinion that Drupal can do whatever it wishes to do with the code that is exclusively shared as part of the Drupal distribution.

Any changes made to the common autoloader to assist members to use one autoloader for full distributions is great, but it should not require a new standard.

This is where nailing down FIG's scope matters. Is FIG about interoperability and shared code? Or, is FIG now going to set standards for distributions, too?

I shared my non-member opinion on this and that is completely irrelevant. But I am asking - does the membership agree on this point?

2. The common practice of folder structures can introduce layers into the install path.

Earlier, Paul you and I disagreed on this. I contend the package folder structure is *not* a standard. It's just a common practice. If another practice is adopted, that's fine. No new standard is needed because there is no standard on this now. It does not matter how projects store files and folders for shared packages. What matters is that they are installed in a predictable way.

3. Composer uses two nodes for it's install path.

If you name your package Vendor-name/Package name - and if we can figure out how to get those nodes to be mixed case, instead of lower case, two more levels are removed. Again, this is not a standard, it's merely an implementation issue.

4. Autoloader

I hacked the autoloader too - https://github.com/Molajo/Standard/blob/master/ClassLoader.php#L233 - I can begin my namespaces anywhere -- that's what you are trying to do too. My approach is PSR-0 compliant.


Paul - I hope there is a way of solving these problems without a second namespacing standard. 

I apologize if I am not supposed to respond since I am not a member. 

Paul Jones

unread,
Apr 3, 2013, 10:59:31 PM4/3/13
to php...@googlegroups.com
I am confused by your statement; it seems contradictory. (I read it as "It's fine to amend, clarify, or change older RFCs; but PSRs should be set in stone.") Can you clarify?


-- pmj

Paul Jones

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

On Apr 3, 2013, at 6:40 PM, Amy Stephen wrote:

> I'm not a member, so, not sure if I am out of line now commenting or not.

Commenting here is never out of line, unless it's unprofessional in some way.

I am going to skip to the end, because that seems the most relevant part of your email.


> 4. Autoloader
>
> I hacked the autoloader too - https://github.com/Molajo/Standard/blob/master/ClassLoader.php#L233 - I can begin my namespaces anywhere -- that's what you are trying to do too. My approach is PSR-0 compliant.

If a loader modifies the transformed class name in any other way than specified by PSR-0, that loader is not PSR-0 compliant. For example, one cannot transform 'Foo\Bar\Baz' to '/some/other/dir/Baz.php'. The class name must always and only be transformed to 'Foo/Bar/Baz.php'. Thus, the hack you have added, while useful (and familiar!), is not PSR-0 compliant.


-- pmj

Amy Stephen

unread,
Apr 3, 2013, 11:26:15 PM4/3/13
to php...@googlegroups.com
Is it the autoloader that must be compliant -- or the result?

My physical paths match the standard, as does my namespace.



--
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/qT7mEy0RIuI/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.

Evert Pot

unread,
Apr 3, 2013, 11:28:35 PM4/3/13
to php...@googlegroups.com
Sorry, that was confusing. Missed half a sentence there.

Basically this:

> modify this proposal to state that complying with it is sufficient to meet the requirement of complying with PSR-0 for the purposes of PSR-1

...is exactly what I meant. Don't change the documents once they are released :)

Cheers,
Evert

Paul Jones

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

On Apr 3, 2013, at 10:28 PM, Evert Pot wrote:

>
> On 4 apr. 2013, at 03:59, Paul Jones <pmjo...@gmail.com> wrote:
>
>>
>> On Apr 3, 2013, at 5:51 PM, Evert Pot wrote:
>>
>>> On Apr 3, 2013, at 11:37 PM, Paul Jones <pmjo...@gmail.com> wrote:
>>>
>>>> PSR-1 states you must comply with PSR-0 to be PSR-1 compliant. Obviously we don't want adopters of this proposal (should it pass) to find themselves out of compliance. So we need to do one of the following:
>>>>
>>>> - modify PSR-0 to say that complying with this proposal (if accepted) is a sufficient alternative
>>>>
>>>> - modify PSR-1 to say "comply with PSR-0 +++or PSR-N+++"
>>>>
>>>> - modify this proposal to state that complying with it is sufficient to meet the requirement of complying with PSR-0 for the purposes of PSR-1
>>>>
>>>> Thoughts, anyone?
>>>
>>> In the IETF world, it's completely fine to amend, clarify or change the meaning of older RFC's.
>>> I think this is the proper way to go about it. Once PSR's are made, they should be set in stone.
>>
>> I am confused by your statement; it seems contradictory. (I read it as "It's fine to amend, clarify, or change older RFCs; but PSRs should be set in stone.") Can you clarify?
>
> Sorry, that was confusing. Missed half a sentence there.

Thank goodness. :-)


> Basically this:
>
>> modify this proposal to state that complying with it is sufficient to meet the requirement of complying with PSR-0 for the purposes of PSR-1
>
> ...is exactly what I meant. Don't change the documents once they are released :)

I am totally fine with this.


-- pmj

Beau Simensen

unread,
Apr 3, 2013, 11:31:31 PM4/3/13
to php...@googlegroups.com
On Wednesday, April 3, 2013 11:47:23 AM UTC-5, pmjones wrote:
- Autoloader implementations MUST allow each namespace prefix to be mapped to multiple directories.
 
Does this need to be specified? I can see specialized PSR-X autoloader implementations that will have no need for supporting multiple directories being mapped. Would it make more sense to either drop this or change MUST to MAY?

Paul Jones

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

On Apr 3, 2013, at 10:26 PM, Amy Stephen wrote:

> Is it the autoloader that must be compliant -- or the result?

The transformation from fully-qualified class name to file name, whereby a class is mapped to particular path in the filesystem, is the relevant issue for this discussion. If the class name 'Foo\Bar\Baz' is transformed to any terminating path other than 'Foo/Bar/Baz.php' then it is not PSR-0 compliant.


-- pmj

Amy Stephen

unread,
Apr 3, 2013, 11:36:33 PM4/3/13
to php...@googlegroups.com
Foo\Bar\Baz transforms to a terminating path for Foo/Bar/Baz.php

I'm just using Composer's two nodes - in mixed case - as my Vendor-name/Project-name




-- pmj

Paul Jones

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

On Apr 3, 2013, at 10:36 PM, Amy Stephen wrote:

> Foo\Bar\Baz transforms to a terminating path for Foo/Bar/Baz.php
>
> I'm just using Composer's two nodes - in mixed case - as my Vendor-name/Project-name

I added one line to the autoloader you linked, changing this starting at line 254 ...

foreach ($dirs as $dir) {
if (file_exists($dir . DIRECTORY_SEPARATOR . $className . '.php')) {
return $dir . DIRECTORY_SEPARATOR . $className . '.php';
}
}

to this (note the added "echo" line):

foreach ($dirs as $dir) {
echo $dir . DIRECTORY_SEPARATOR . $className . '.php' . PHP_EOL;
if (file_exists($dir . DIRECTORY_SEPARATOR . $className . '.php')) {
return $dir . DIRECTORY_SEPARATOR . $className . '.php';
}
}


Therafter, running this script:

$loader = new ClassLoader;
$loader->add('Foo\Bar', '/path/too/foo.bar');
$loader->findFile('Foo\Bar\Baz');

Results in this output:

/path/too/foo.bar/Baz.php

That transformation is not PSR-0 compliant.


-- pmj

Beau Simensen

unread,
Apr 3, 2013, 11:47:31 PM4/3/13
to php...@googlegroups.com
On Wednesday, April 3, 2013 10:43:17 PM UTC-5, pmjones wrote:

    $loader = new ClassLoader;
    $loader->add('Foo\Bar', '/path/too/Foo/Bar');
    $loader->findFile('Foo\Bar\Baz');

Results in this output:

    /path/too/Foo/Bar/Baz.php

What about in this case? Would this particular transformation be considered PSR-0 compliant? I'd be hard pressed to say no, even though I kinda really want to. :)

I think the argument is that in some cases, when the vendor and package are Foo/Bar and you can use the desired case, you can get away with this and call it PSR-0 compliant?

Andrew Eddie

unread,
Apr 3, 2013, 11:51:29 PM4/3/13
to php...@googlegroups.com
On Thursday, 4 April 2013 08:37:18 UTC+10, pmjones wrote:
So we need to do one of the following:

- modify PSR-0 to say that complying with this proposal (if accepted) is a sufficient alternative

- modify PSR-1 to say "comply with PSR-0 +++or PSR-N+++"

- modify this proposal to state that complying with it is sufficient to meet the requirement of complying with PSR-0 for the purposes of PSR-1

I'm sorry I haven't read the proposal in detail (I'm working on the principle that if Don is happy, I'm happy), but does it comply with PSR-0 out of the box? If so, there is no need to worry about PSR-1 because you would comply by inheritance. I assume autoloaders would just have to have a switch for PSR-0 or PSR-4(?) mode.

If this proposal is not strictly PSR-0 compliant, then I would generate a new PSR-5(?) based on PSR-1 to reference this new PSR-4(?) autoloader standard and leave PSR-0 and 1 cast in stone. That way there is no confusion about someone saying they are PSR-1 compliant but not really knowing with autoloader standard they are using.

Regards,
Andrew Eddie


Amy Stephen

unread,
Apr 4, 2013, 12:00:47 AM4/4/13
to php...@googlegroups.com
Paul - I'm using this ClassLoader.

findFile (line 213) traverses a directory - looking for a file. Are you saying you have a file /path/too/foo.bar/Baz.php in your test bed?

What directory structure are you using?






-- pmj

Paul Jones

unread,
Apr 4, 2013, 12:06:02 AM4/4/13
to php...@googlegroups.com

On Apr 3, 2013, at 10:47 PM, Beau Simensen wrote:

> On Wednesday, April 3, 2013 10:43:17 PM UTC-5, pmjones wrote:
>
> $loader = new ClassLoader;
> $loader->add('Foo\Bar', '/path/too/Foo/Bar');
> $loader->findFile('Foo\Bar\Baz');
>
> Results in this output:
>
> /path/too/Foo/Bar/Baz.php
>
> What about in this case? Would this particular transformation be considered PSR-0 compliant?

Yes; the fully qualified class name has been transformed to a terminating path according the the PSR-0 rules. (The leading portion, "/path/too", is not defined in PSR-0.)



-- pmj

Paul Jones

unread,
Apr 4, 2013, 12:13:11 AM4/4/13
to php...@googlegroups.com

On Apr 3, 2013, at 10:51 PM, Andrew Eddie wrote:

> On Thursday, 4 April 2013 08:37:18 UTC+10, pmjones wrote:
> So we need to do one of the following:
>
> - modify PSR-0 to say that complying with this proposal (if accepted) is a sufficient alternative
>
> - modify PSR-1 to say "comply with PSR-0 +++or PSR-N+++"
>
> - modify this proposal to state that complying with it is sufficient to meet the requirement of complying with PSR-0 for the purposes of PSR-1
>
> I'm sorry I haven't read the proposal in detail (I'm working on the principle that if Don is happy, I'm happy)

Not at all; we're all busy around here.


> but does it comply with PSR-0 out of the box? If so, there is no need to worry about PSR-1 because you would comply by inheritance. I assume autoloaders would just have to have a switch for PSR-0 or PSR-4(?) mode.

Kind of (which is to say "no, no strictly, but you can make it look like it does").

For a PSR-0 lookalike transformation, you would have to register the path of the empty vendor and package directories. Say you have this structure:

/path/to/foo.bar
src/
Foo/
Bar/
Baz.php

Under PSR-0 proper you would register like so:

$loader->add('Foo\Bar', '/path/to/foo.bar/src');

But under this proposal, you would have to register like so:

$loader->addNamespacePath('Foo\Bar', '/path/to/foo.bar/src/Foo/Bar');

Then loading 'Foo\Bar\Baz' would work as it does under PSR-0 (where you do not need to specify the "Foo/Bar" part of the path when registering.)

However, the proposal *does not* honor underscores as directory separators in the class name portion, so 'Foo\Bar\Baz_Dib' would *not* be transformed to 'Foo/Bar/Baz/Dib.php'; the underscore would be left in place.


> If this proposal is not strictly PSR-0 compliant, then I would generate a new PSR-5(?) based on PSR-1 to reference this new PSR-4(?) autoloader standard and leave PSR-0 and 1 cast in stone. That way there is no confusion about someone saying they are PSR-1 compliant but not really knowing with autoloader standard they are using.

Then we would have to create PSR-6 to modify PSR-2 because it references PSR-1. Yay for cascading references!


-- pmj

Paul Jones

unread,
Apr 4, 2013, 12:14:27 AM4/4/13
to php...@googlegroups.com

On Apr 3, 2013, at 11:00 PM, Amy Stephen wrote:

> Paul - I'm using this ClassLoader.
>
> findFile (line 213) traverses a directory - looking for a file. Are you saying you have a file /path/too/foo.bar/Baz.php in your test bed?

The point is that it's transforming the class name to a path according to a rule *other* than that described by PSR-0.


-- pmj





Hari K T

unread,
Apr 4, 2013, 12:16:42 AM4/4/13
to php...@googlegroups.com
Hey ,

Paul, I guess the best example currently to show will be

https://github.com/sebastianbergmann/pson/blob/master/src/Serializer.php

Is this the right one ?






--
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 4, 2013, 12:36:00 AM4/4/13
to php...@googlegroups.com
Hey Hari - What does that show? Not following.


--
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/qT7mEy0RIuI/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 4, 2013, 12:39:25 AM4/4/13
to php...@googlegroups.com
How will this impact Composer?

What if I want to bring in packages that uses the two different standards?

Can the new standard supersede the old standard so that there is one standard and one autoloader strategy?






-- pmj





Andrew Eddie

unread,
Apr 4, 2013, 12:39:22 AM4/4/13
to php...@googlegroups.com
On 4 April 2013 14:13, Paul Jones <pmjo...@gmail.com> wrote:
Then we would have to create PSR-6 to modify PSR-2 because it references PSR-1.  Yay for cascading references!

Heh, seemed like a good idea at the time :) Fortunately we aren't cutting down real trees to print all the new PSR (just burning more coal and yellow-cake to keep the extra photons and electrons flowing).

Regards,
Andrew Eddie

Paul Jones

unread,
Apr 4, 2013, 12:55:03 AM4/4/13
to php...@googlegroups.com

On Apr 3, 2013, at 11:39 PM, Andrew Eddie wrote:

> On 4 April 2013 14:13, Paul Jones <pmjo...@gmail.com> wrote:
> Then we would have to create PSR-6 to modify PSR-2 because it references PSR-1. Yay for cascading references!
>
> Heh, seemed like a good idea at the time :)

I think Napoleon said that about Waterloo. ;-)

No, I think Evert's idea of specifying in the proposal that the PSR-1 requirement to follow PSR-0 is amended to include the new proposal (provided it passes) is reasonable.


-- pmj

Andrew Eddie

unread,
Apr 4, 2013, 1:09:59 AM4/4/13
to php...@googlegroups.com
On 4 April 2013 14:55, Paul Jones <pmjo...@gmail.com> wrote:
No, I think Evert's idea of specifying in the proposal that the PSR-1 requirement to follow PSR-0 is amended to include the new proposal (provided it passes) is reasonable.

If, for example, Symfony goes with PSR-1+4 but Doctrine sticks with PSR-1+0, but both state they are PSR-1 compliant is that going to cause an interoperability issue?

Regards,
Andrew Eddie

Hari K T

unread,
Apr 4, 2013, 1:30:09 AM4/4/13
to php...@googlegroups.com
Hi Amy,

Hey Hari - What does that show? Not following.


I thought an example will help. When we look into https://github.com/sebastianbergmann/pson . You can see the src folder .

and when we look a file, say Serializer it is following the above standard Paul was mentioning. May be projects like that will help to autoload .
namespace SebastianBergmann\PSON
{
}


or may be I am wrong also.

And I love PSR-0, for the consistency and I fear people using 2 different PSR and later causing
trouble.

Also I am in a dialama wondering whether this is a way to go or not. Anyway for I am not a voting member
I will wait what the outcome is.

Also at-times I feel your point is correct that we are trying to solve the module problem for CMS and
not the library.

I cannot think more for the current time, but I will hear what others say and how this goes well.

Pádraic Brady

unread,
Apr 4, 2013, 7:13:34 AM4/4/13
to php...@googlegroups.com
Hi Andrew,

If we amend PSR-1 through PSR-X, PSR-1's text is incorrect by definition. A reading of PSR-1 would also require a reading of PSR-X (you see this all the time in legislation with Amendment/Consolidation Acts). So the devil is in the wording. Does the end result require a project to follow one or both autoloading approaches? If both, then Doctrine's assertion is wrong - they would fall out of compliance along with everyone else currently implementing PSR-0 only.

I'm not a huge fan of looping the spacetime continuum to avoid the obvious - just editing PSR-1 itself. If we're going to change what PSR-1 says, then we should edit it directly and avoid any confusion. Otherwise we now have to explain that to understand PSR-1, you must read PSR-1 AND PSR-4.

Secondly, we all know which can of worms this opens... Once you edit a standard (directly or indirectly), we've established the precedent that the intent and content of a PSR is editable without replacing the standard. I'm not saying that's good or bad - merely that the door would be opened and we lack a bylaw governing those changes or putting a limit on what is and is not allowable.

In any case, this discussion will hijack the rest of Paul's proposal so I'd suggest separating it into another thread. I'll start one if nobody else does shortly...

Paddy

Jason Judge

unread,
Apr 4, 2013, 7:19:24 AM4/4/13
to php...@googlegroups.com
I'm not sure if this helps or not, but I *think* I see parallels in parts of this proposal to what we used to do on PHP4 CMS many moons ago.

This was before namespaces and proper OOP, but all the functions were prefix-namespaced. The functions were then located - one per file - in a directory structure that followed the namespace prefix. So function articles_admin_create() was located in [modules]/articles/admin/create.php and could be loaded on demand when we needed it.

Now, this also incurred a certain amount of overhead, because many files were being loaded. Remember this was in the days before byte-caching and cheap memory. To reduce the number of files that needed to be loaded on each page, some functions were moved down the directory tree and grouped together. So articles_admin_create() could be in articles/admin/create.php, but if that did not exist, then it would be in articles/admin.php If it was not in there, then it would be in articles.php

Of course, that meant each script could contain multiple functions, all of which would be loaded at the same time if you needed just one. Bit then, the developer would put all the functions that they *knew* would be needed every time into the same file, so loaded all at once was the whole idea that brought a benefit.

The parallels I see in this proposal, are the shortening of the directory tree for some classes. This would mean the namespace of those classes does not match the directory structure 1:1, but does share the path to a point - the point being the first php script that the class is found in (using a depth-first search).

How it differs is that the php script we would use at the lower diectory would be named after the next level in the namespace, and not the class or function name. Following that convention, Foo\Bar\Baz\Dib\Zim\Gir() could be in Foo\Bar\Baz\Dib\Zim\Gir.php or Foo\Bar\Baz\Dib\Zim.php or Foo\Bar\Baz\Dib.php etc. A consequence of that is that each php script would need to be able to hold not just multiple classes, but also multiple namespaces. However, if I am reading this proposal correctly, it is still possible that you may want to put multiple classes into one script, since both Baz\Dib\Zim\Gir() and Baz\Dab\Zim\Gir() could both be located in Baz\Gir.php

It should be noted here that I am ignoring where the base directory is, e.g. where Composer puts its packages or module developers start the namespace tree. That is a completely different thing.

Anyway, that may be something you want to absolutely avoid, but it did nicely get us over resource issues in what we had to play with ten years ago (the Xaraya CMS project). Hopefully this will help see how things can be pieced together, and not just confuse the proposal with irrelevancy.

-- Jason


On Wednesday, 3 April 2013 17:47:23 UTC+1, pmjones wrote:
Greetings all,

N.b.: If this proposal is adopted, PSR-1 MUST be be amended so that the requirement to follow PSR-0 becomes a requirement to follow either PSR-0 or this proposal.

Let the beatings commence!

* * *


Package-Oriented Autoloader
===========================

Introduction
------------

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.

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.

However, with the recent proliferation of packages, modules, and bundles in PHP, we note that conforming to the PSR-0 standard leads to deeper empty directory structures in distributions, like the following:

    Foo_Bar_Package/
        src/
            Foo/
                Bar/
                    Baz.php       # Foo\Bar\Baz
        tests/
            Foo/
                Bar/
                    BazTest.php   # Foo\Bar\BazTest

The behavior has been noted as problematic:

- <https://igor.io/2013/01/23/autoload-insanity.html>
- <https://groups.google.com/d/msg/php-fig/-BPdegzme_Y/ZVR_4gVMoIkJ>

This proposal seeks to provide an *alternative to* (not a *replacement for*) PSR-0 that allows for a structure that makes the directory structures less deep, like the following:

    Foo_Bar_Package/
        src/
            Baz.php       # Foo\Bar\Baz
        tests/
            BazTest.php   # Foo\Bar\BazTest

Additionally, since the use of underscores in class names was to represent pseudo-namespaces in PHP 4 to PHP 5.2.x, their use when namespaces proper are available is no longer necessary. This removes possible conflicts between `Foo\Bar` and `Foo_Bar`.


Rules
-----

(The term "class" below refers to classes, interfaces, and traits.)

- Fully-qualified class names MUST begin with a top-level namespace name, which MUST be followed by zero or more sub-namespace names, and MUST end in a class name.

- Class files MUST contain only one class definition.

- Autoloader implementations MUST map a namespace prefix to a directory.

- Autoloader implementations MUST allow each namespace prefix to be mapped to multiple directories.

- Autoloader implementations MUST map the non-namespace-prefix portion of the fully-qualified class name to a sub-path by replacing namespace separators with directory separators, and MUST suffix the result with `.php`.
 
- Autoloader implementations MUST search for class files among their registered namespace prefixes in a depth-first fashion.

- Autoloader implementations MUST search the paths for a registered namespace in the order those paths were registered.
 

Narrative
---------

Given the below example implementation, and a `Foo\Bar` package of classes, one would register the path to "source" files and "unit test" files for the namespace prefix like so:

    // instantiate the loader
    $loader = new PackageOrientedLoader;
   
    // register the source file paths for the namespace prefix
    $loader->addNamespacePath(
        'Foo\Bar',
        '/path/to/Foo.Bar/src'
    );

    // register the unit test paths for the namespace prefix
    $loader->addNamespacePath(
        'Foo\Bar',
        '/path/to/Foo.Bar/tests'
    );

Given a package in a "sub-namespace" of `Foo\Bar\Baz\Dib`, one would register the "sub-package" like so:

    $loader->addNamespacePath(
        'Foo\Bar\Baz\Dib',
        '/path/to/Foo.Bar.Baz.Dib/src'
    );

When the autoloader calls `load()` for a fully-qualified class name of `Foo\Bar\Baz\Dib\Zim\Gir`, the implementation will search the registered paths in this order:

    - first, for `/path/to/Foo.Bar.Baz.Dib/src/Zim/Gir.php`;
    - then, for `/path/to/Foo.Bar/src/Baz/Dib/Zim/Gir.php`;
    - last, for `/path/to/Foo.Bar/test/Baz/Dib/Zim/Gir.php`;

Note that the longest registered namespace prefix that matches the fully-qualified class name is searched first, and the shortest is searched second.  When a registered namespace prefix has multiple paths, the paths are searched in the order they were registered.


Example Implementation
----------------------

The following is one possible implementation of the rules described above.

    <?php
    /**
     * An example implementation for a package-oriented autoloader.
     */
    class PackageOrientedAutoloader
    {
        /**
         *
         * An array where the key is a namespace prefix, and the value is a
         * sequential array of directories for classes in that namespace.
         *
         * @var array
         *
         */
        protected $paths = array();
   
        /**
         *
         * Adds a path for a namespace prefix.
         *
         * @param string $ns The namespace prefix.
         *
         * @param string $path The directory containing classes in that
         * namespace.
         *
         * @return void
         *
         */
        public function addNamespacePath($ns, $path)
        {
            $path = rtrim($path, DIRECTORY_SEPARATOR);
            $this->paths[$ns][] = $path;
        }

        /**
         *
         * Loads the class file for a fully qualified class name.
         *
         * @param string $fqcn The 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;
        }

        /**
         *
         * Uses `require` to read a file from the filesystem.
         *
         * @param string $file
         *
         * @return bool True if the file gets read; false if it does not.
         */
        protected function readFile($file)
        {
            if (! is_readable($file)) {
                return false;
            }

            require $file;
            return true;
        }
    }

* * *


-- pmj

Jason Judge

unread,
Apr 4, 2013, 7:28:03 AM4/4/13
to php...@googlegroups.com
To clarify, it looks to me like this proposal may be dealing more with trimming the lower part of the namespace-matching directory tree, to cut down on those empty directories, while my experience is more about trimming the higher (deeper) end of the directory tree. However, by allowing the higher levels to be trimmed and classes to be grouped into single files, those lower-level Vendor-name/Package-name directories may not actually be empty; they could contain base classes that are perhaps always needed whenever the package is used.

Best practices tend to change with the tools, so the idea of putting multiple namespaced classes into one script may be an evil thing for me to suggest ;-)

-- Jason


Andrew Eddie

unread,
Apr 4, 2013, 7:46:48 AM4/4/13
to php...@googlegroups.com
On 4 April 2013 21:13, Pádraic Brady <padrai...@gmail.com> wrote:
In any case, this discussion will hijack the rest of Paul's proposal so I'd suggest separating it into another thread. I'll start one if nobody else does shortly...

Fair enough on the point on how to change a PSR. However, I think there is an issue to discuss about whether PSR-1 should be tightly coupled to PSR-0 or any other for that matter. Is the important thing about PSR-1 that we use PSR-0, or that *a* standard for namespacing is adopted? Would it matter to PSR-1 if the vendor used Adhoc-Autoloader-Standard-42?

In other words, is the requirement "Namespaces and classes MUST follow PSR-0." actually important?

Regards,
Andrew Eddie

Phil Sturgeon

unread,
Apr 4, 2013, 8:31:03 AM4/4/13
to php...@googlegroups.com
Andrew: 

If, for example, Symfony goes with PSR-1+4 but Doctrine sticks with PSR-1+0, but both state they are PSR-1 compliant is that going to cause an interoperability issue?

Nope! Projects should be able to pick their style guide (PSR-1 and maybe PSR-2) then pick their autoloader (PSR-0 OR PSR-X). The change Paul suggested to PSR-1 would this extremely clear.

Amy:

How will this impact Composer? 

It wont, other than the Composer team will need to support a new option in the composer.json:

     "autoload": {
          "psr-X": {
          }
      },

 What if I want to bring in packages that uses the two different standards?

Then they'll be fine. Because PSR-0 (or PSR-X) compliance starts at the package specific defined folder (not the root vendor/ folder) you could easily mix and match PSR-0 and PSR-X in the exact same way you can mix in old PHP 5.2 classmap'ed stuff already.

Pádraic:

Does the end result require a project to follow one or both autoloading approaches? 

It would definitely need to be one or the other. 

* Namespaces and classes MUST follow PSR-0+++ OR PSR-X+++.

I think we should keep discussions on "Can we change a PSR" on this topic:


This will allow us to continue discussing JUST the new autoloader, then if that other thread leads to a vote and it passes we can ammend PSR-1 and be on our way, otherwise we can make PSR-6, 7 and 8 and be done.

Benjamin Eberlei

unread,
Apr 4, 2013, 8:39:17 AM4/4/13
to php...@googlegroups.com
On Wed, Apr 3, 2013 at 6:47 PM, Paul Jones <pmjo...@gmail.com> wrote:
Greetings all,

N.b.: If this proposal is adopted, PSR-1 MUST be be amended so that the requirement to follow PSR-0 becomes a requirement to follow either PSR-0 or this proposal.

Let the beatings commence!

Why even formalize this? You can just use the "classmap" autoloading for a Composer package that doesn't follow PSR-0 and be done with it. I don't see why we need to add all this additional complexity (if then autoload x else then autoload y). If/Else in specifications are bad, why introduce them :-(


-- pmj

--

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.

Phil Sturgeon

unread,
Apr 4, 2013, 8:43:54 AM4/4/13
to php...@googlegroups.com
Why even formalize this? You can just use the "classmap" autoloading for a Composer package that doesn't follow PSR-0 and be done with it. 

Sure, but PSR-1 not using PSR-0 would break its PSR-1yness in the first place so thats not really relevant.

PSR-1 just needs to say:

* Namespaces and classes MUST follow PSR-0+++ OR PSR-X+++.

Thats not if/else or confusing or anything else, it needs to be one of the two and users can pick whichever they feel is best. 

Andrew Eddie

unread,
Apr 4, 2013, 9:21:37 AM4/4/13
to php...@googlegroups.com
On 4 April 2013 22:31, Phil Sturgeon <em...@philsturgeon.co.uk> wrote:
Then they'll be fine. Because PSR-0 (or PSR-X) compliance starts at the package specific defined folder (not the root vendor/ folder) you could easily mix and match PSR-0 and PSR-X in the exact same way you can mix in old PHP 5.2 classmap'ed stuff already.

If that's the case then I'm fine with the amendment to PSR-1 (however that ends up happening).

Though, in doing that, you most certainly set a precedent for another PSR being amended to support ^%^%^ OR #@#@#@ indentation :P

Regards,
Andrew Eddie 

Phil Sturgeon

unread,
Apr 4, 2013, 9:29:26 AM4/4/13
to php...@googlegroups.com
Ha! No thanks. :)

If we're clear about the reasoning for amendments, we only allow amendments do not change the main content and maintain backwards compatibility. That doesn't mean we can just throw in "Aaand.... your docblock MUST have at least one ASCII image of a Unicorn" but it does mean updating a PSR to say "oh or you could use our new autoloader instead" should be acceptable.

Paul Jones

unread,
Apr 4, 2013, 9:40:39 AM4/4/13
to php...@googlegroups.com
I don't think so. As long as people using both projects have appropriate autoloader implementations, I have a hard time thinking up conflicts.


-- pmj

Donald Gilbert

unread,
Apr 4, 2013, 9:48:21 AM4/4/13
to php...@googlegroups.com

... (I'm working on the principle that if Don is happy, I'm happy), ...

Thanks Andrew! :)

The main benefit of the new proposal is that you can map any namespace to any directory location that you'd prefer. It makes overriding classes more simple, IMO. It would help us, as it is one feature that we lost when we switch the Joomla Framework from our own more flexible JLoader to the composer PSR-0 autoloader. 

Donald Gilbert

unread,
Apr 4, 2013, 9:56:00 AM4/4/13
to php...@googlegroups.com
Amy, I know you know this, but the autoload part of the schema can take multiple mapping types. You currently can specify psr-0, files, classmap, etc. So it would seem that composer is already in place to take additional parameters, so it would be as simple as adding to your composer.json

{
    "autoload": {
        "psr-N": {
            "Joomla\Application": "./"
        }
    }
}

I suppose as a dev, you would want to stick with one autoloading strategy for your package, just to avoid having to answer that question. :)

IMO, the new could not replace or supercede, simply due to PSR-0's broad use. I mean, maybe it could, but it would pretty difficult to mandate.

Amy Stephen

unread,
Apr 4, 2013, 10:52:08 AM4/4/13
to php...@googlegroups.com
On Thu, Apr 4, 2013 at 7:31 AM, Phil Sturgeon <em...@philsturgeon.co.uk> wrote:
Amy:

How will this impact Composer? 

It wont, other than the Composer team will need to support a new option in the composer.json:

     "autoload": {
          "psr-X": {
          }
      },

 What if I want to bring in packages that uses the two different standards?

Then they'll be fine. Because PSR-0 (or PSR-X) compliance starts at the package specific defined folder (not the root vendor/ folder) you could easily mix and match PSR-0 and PSR-X in the exact same way you can mix in old PHP 5.2 classmap'ed stuff already.


This is my major concern.

I am not convinced a new standard is needed. But, if the result does not negatively impact interoperability my huge concerns are gone.

Amy Stephen

unread,
Apr 4, 2013, 10:54:44 AM4/4/13
to php...@googlegroups.com
On Thu, Apr 4, 2013 at 8:21 AM, Andrew Eddie <mamb...@gmail.com> wrote:

Though, in doing that, you most certainly set a precedent for another PSR being amended to support ^%^%^ OR #@#@#@ indentation :P

Regards,
Andrew Eddie


And rightly so. This is being done for cosmetic reasons, too. 

Amy Stephen

unread,
Apr 4, 2013, 11:08:51 AM4/4/13
to php...@googlegroups.com
Don - Phil assured me that packages that use one or the other autoload strategy can be combined by Composer at installation. That's my major concern. I suppose those projects maintaining their own installers might need to adapt, but, maybe they'll just use Jordi's fine work.

As far as the standard, it could be developed in support of PSR-0 with additional options for these tweaks, and then one and only one standard would result. That's my point. In no way am I suggesting those who are compliant now be forced to change.

If Phil says it's all good and groovy - then I'm not objecting.

It's a slippery slope, but we are the Internets and we love our drama! ;-)


--
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/qT7mEy0RIuI/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.
To view this discussion on the web visit https://groups.google.com/d/msg/php-fig/-/hZ75AuUkqY4J.

Phil Sturgeon

unread,
Apr 4, 2013, 12:58:35 PM4/4/13
to php...@googlegroups.com
I'm confident that even despite all the "should we or shouldn't we change PSR's" this would be too big of a change to even consider. Its fundamental, and would break PSR-0 users everywhere (especially the way im using it, which is a valid usage), so lets not do that.

Reading through all of your Gists and stuff Amy I thought you would be entirely in support of this new autoloader, as it reduces the doubling up of folder structure.

PSR-0 does what it does and it's not perfect. It means you need more folder structure to use it in installable packages and it has known quirks, so making this new and improved PSR-X (PSR-4 if its done quickly) would take care of what you want PSR-0 to do and allow PSR-0 packages and PSR-X packages to co-exist perfectly, all the while maintaining my PSR-0 folder structure example so we're not breaking Joomla, Drupal and PyroCMS with the change. Users wont notice the difference and can continue to install components, and from the outside it will make no difference at all, but it will allow package devs more control over what goes where.

That's a win win for me! Go Paul.

Amy Stephen

unread,
Apr 4, 2013, 1:56:26 PM4/4/13
to php...@googlegroups.com
Phil -

First of all *hugs* for reading my gist. I don't want to continue to
repeat those points since those of us who have dug into this know
there are a number of factors and the discussion becomes overly
complex and confusing.

My disagreements are listed in order of priority:

1. Concern that packages using different NS standards could not be
used together and installed with Composer. - You have reassured me on
this point that such is not the case. Check.

2. My hope that we could avoid another standard and address the
problem by adapting our practices: the folder structure
*recommendations* and seeing if Composer would consider allow those
first two nodes following vendor to be mixed case. Combined, those two
changes in practice, alone, would allow install paths like this (even
this new standard won't get that short of install paths):

vendor/Molajo/FieldHandler/Type/Alpha.php

And a namespace:

Molajo\FieldHandler\Type\Alpha

3. My belief that part of the problem that the proposal attempts to
solve is outside of the scope of PSR-0 and FIG in that it addresses
files and folders that are NOT shared between projects, but rather
specific to that particular project's distribution. I love it that a
shared autoloader is being developed to help with that problem and I
shared in the other thread with Larry how I dealt with that issue,
too. But, it's my opinion that collaboration can be done without
impact to the standard.

4. Tabs and spaces. Brackets on Lines. There is a never ending list of
let's do it this way that follows once the finger is pulled out of the
dyke on changing standards.

I don't get to vote - but if I did - I would challenge those of you
proposing this to keep the shared packages the way they are and to
collaborate on adaptation to the autoloader outside of the standard.
Then, I'd pass a hat to raise funds to see if Jordi can help us out on
those first two Composer nodes.

I'm sorry not to be supportive of this, I just can't quite get there.
Never fear - I do not vote. =)
> --
> 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/qT7mEy0RIuI/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.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/php-fig/-/Txgr7VuvByIJ.

Igor Wiedler

unread,
Apr 4, 2013, 2:12:27 PM4/4/13
to php...@googlegroups.com
Hi,

First of all, thanks to you guys for picking this up and actually moving forward with it. Kudos! It goes without saying that I support this proposal.

I would like to bring up a minor concern though. I fear that the current proposal is over-specified. It specifies a lot of implementation details that really don't matter so much. Compare this to PSR-0, which just specified a set of path rewriting rules.

I think it would be beneficial if lots of those details were removed from the proposal. Even the concept of "an autoloader" and any state associated with it should be avoided. After all, an autoloader is not an object. From PHP's perspective, it's just a function (a PHP callable) that loads stuff. That's how it should be specified IMO.

Either way, having an alternative to PSR-0 is a good idea.

Regards,

Igor

Phil Sturgeon

unread,
Apr 4, 2013, 3:09:37 PM4/4/13
to php...@googlegroups.com
Amy: I thought we'd come close to an agreement but now im confused again.

2. My hope that we could avoid another standard and address the 
problem by adapting our practices: the folder structure 
*recommendations* and seeing if Composer would consider allow those 
first two nodes following vendor to be mixed case. Combined, those two 
changes in practice, alone, would allow install paths like this (even 
this new standard won't get that short of install paths): 
    vendor/Molajo/FieldHandler/Type/Alpha.php 

Nooooooo! This is you trying to put PSR-0 into the root of Composer's vendor folder instead of leaving PSR-0 inside a specific package. This is not a fault of PSR-0, this is by design of Composer because it needs to remain completely standards agnostic. Because Composer IS totally standard agnostic it means we CAN support multiple autoloaders, instead of trying to change PSR-0 and breaking everything. Composer and PSR-0 need to remain exactly as they are.

As I see it, those proposed folders will never be supported (and shouldn't be) unless people want to use the SplAutoloader and point it as the vendor/ dir themselves, somewhat like Drupal do and very much like what I do, but with multiple "vendor" type folders instead of one. 

So again, PSR-0 is doing exactly what it should be, and Composer is keeping itself to be completely agnostic, both of which things are absolutely spot on.


3. My belief that part of the problem that the proposal attempts to 
solve is outside of the scope of PSR-0 and FIG in that it addresses 
files and folders that are NOT shared between projects, but rather 
specific to that particular project's distribution. I love it that a 
shared autoloader is being developed to help with that problem and I 
shared in the other thread with Larry how I dealt with that issue, 
too. But, it's my opinion that collaboration can be done without 
impact to the standard. 

The PHP-FIG is not just about making Composer work, it's about being able to share code with common namespacing and autoloading. We could use ZIP files to share Zend code and they would drop right into my PSR-0 autoloaded folder and it would work perfectly. This is just Composer confusing your views on what PSR-0 should be doing again.


Read this again and think about these points:
  • PSR-0 doesn't talk about Composer at all
  • PSR-0 mentions autoloader interoperability, so Composer is just one autoloader of potentially many
  • There are many autoloaders (not just the one Composer uses), but what if somebody built another dependency manager?
PSR-0 is the very basics of interoperability for autoloading code. Composer needs to be standards agnostic, and PSR-0 needs to support multiple autoloaders. That is why - while it might not seem ideal - the integration between the two is a little finicky, which is why PSR-X is being thought up to make this better.

4. Tabs and spaces. Brackets on Lines. There is a never ending list of 
let's do it this way that follows once the finger is pulled out of the 
dyke on changing standards. 

Why are you talking about tabs and spaces? If you're making a reference to if PSR-1 should be changed, then again you need to consider the scope. Making a change to tabs or spaces would break BC and affect the standard. Adding an "PSR-0 ++or PSR-4++" wont break a thing, so this again is something I would not be concerned about.

Amy Stephen

unread,
Apr 4, 2013, 4:09:39 PM4/4/13
to php...@googlegroups.com
Phil - my message has been pretty consistent on this. Remember, I'm
talking about solving the problem with best practices, not standards.

That does not imply anyone *has to* do it that way or that Composer
has an official role in this and more than the folder structure does.
Already, we choose what to name our packages -- my point is that if we
choose to name those Vendor-name/Package-name (most do) - and if those
were permitted to be mixed case, we'd have two nodes.

Further using a folder system that starts at root, rather than src,
and you have the shorteset install path ever. (And still meet PSR-0).

Many people do not care about this. No one *has* to use those
practices, but if they were disturbed about the install path length,
this would be an approach they could use. To me, that's good enough.

You apparently don't agree, and that's fine. But I see no need for the
two of us to go back and forth on this. I don't even vote. Thanks for
hearing me. Let's see what others and esp the members think.
> --
> 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/qT7mEy0RIuI/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.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/php-fig/-/jzHGyvSe73MJ.

Phil Sturgeon

unread,
Apr 4, 2013, 4:45:37 PM4/4/13
to php...@googlegroups.com
So you are trying to PSR-0 the entire composer namespace, my understand of your intentions doesn't seem far off, I just assumed you were confused. If you actually want this to happen, I'll help out by explaining the pros and cons of each approach.

Pauls Solution

Pros
  • Removes the double-nested vendor names
  • Gives extra controls over filesystem -> namespace mapping
  • Removes the conflict between _ and - for PSR-0
  • Maintains the ability to put the autoloadable code into a different folder (src/ or lib/) as is convention
Cons
  • Requires a potential tweak to PSR-1 (being discussed and voted upon already)

Your Solution

Pros
  • Removes the double-nested vendor names
Cons
  • Requires coercing the Composer team into support capital letters for their vendor and package names, which they haven't done for a reason - I assume its a good one
  • Removes the ability for vendor names to have "-" OR transform package-name to PackageName, which means two packages or even two vendors could conflict: some-vendor +  SomeVendor = BOOM
  • Make some packages look like PSR-0, but other packages wouldn't be, meaning vendor is full of some capital and some not. Weird
  • Means a developer who wants to go this route cannot use src/ or lib/ so their tests get jammed right in next to other autoloadable classes...
  • Maintains the conflict between _ and - for PSR-0
  • By setting the root of vendor/ case insensitive file-systems are going to try loading doctrine/common as \Doctrine\Common, which Im sure if not fatal is going to cause confusion and potential performance issues
I feel its rather safe to say my thoughts on the two approaches are not based on a personal disagreement, but more that your solution is fundamentally flawed and a nasty hack. I'd much rather see a new optional autoloader take care of this instead.

Phil Sturgeon

unread,
Apr 4, 2013, 4:59:07 PM4/4/13
to php...@googlegroups.com
Oh wow my first sentence there was written like I learned English last week!

So you are trying to PSR-0 the entire composer vendor directory. My understanding of your intentions doesn't seem far off, I just assumed you were confused because it sounded a bit crazy. If you actually want this to happen, I'll help out by explaining the pros and cons of each approach.

Sorry about that! :)

Paul Jones

unread,
Apr 11, 2013, 8:00:26 PM4/11/13
to php...@googlegroups.com
Greetings all,

I have edited the proposal based on everyone's input so far. The substantive changes are:

- Removed links to external pages (Jordi Boggiano)

- Replaced the requirement that implementations must search the paths in the order registered with a requirement that implementations allow both prepending and appending to the paths (Donald Gilbert)

Regarding Beau Simensen's comment:

>> - Autoloader implementations MUST allow each namespace prefix to be mapped to multiple directories.
>
> Does this need to be specified? I can see specialized PSR-X autoloader implementations that will have no need for supporting multiple directories being mapped. Would it make more sense to either drop this or change MUST to MAY?

I think it's necessary to allow it, so that users who expect to be able to map multiples using one implementation, can still do so in other implementations.

Please find the new proposal below, and let the beatings re-commence.

* * *

Package-Oriented Autoloader
===========================

(The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119][].)

[PSR-0]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
[PSR-1]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md
[RFC 2119]: http://tools.ietf.org/html/rfc2119

1. Background
-------------

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.

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.

However, with the recent proliferation of packages, modules, and bundles in PHP, we note that conforming to the [PSR-0][] standard leads to deeper empty directory structures in distributions, like the following:

Foo_Bar_Package/
src/
Foo/
Bar/
Baz.php # Foo\Bar\Baz
tests/
Foo/
Bar/
BazTest.php # Foo\Bar\BazTest

This proposal seeks to provide an *alternative to* (not a *replacement for*) [PSR-0][] that allows for a structure that makes the directory structures less deep, like the following:

Foo_Bar_Package/
src/
Baz.php # Foo\Bar\Baz
tests/
BazTest.php # Foo\Bar\BazTest

Additionally, since the use of underscores in class names was to represent pseudo-namespaces in PHP 4 to PHP 5.2.x, their use when namespaces proper are available is no longer necessary. This removes possible conflicts between `Foo\Bar` and `Foo_Bar`.


2. Specification
----------------

(The term "class" refers to classes, interfaces, and traits.)

- Fully-qualified class names MUST begin with a top-level namespace name, which MUST be followed by zero or more sub-namespace names, and MUST end in a class name.

- Class files MUST contain only one class definition.

- Autoloader implementations MUST map a namespace prefix to a directory.

- Autoloader implementations MUST allow each namespace prefix to be mapped to multiple directories.

- Autoloader implementations MUST allow directory mappings to be appended or prepended to the existing directory mappings for that namespace prefix.

- Autoloader implementations MUST map the non-namespace-prefix portion of the fully-qualified class name to a sub-path by replacing namespace separators with directory separators, and MUST suffix the result with `.php`.

- Autoloader implementations MUST search for class files among their registered namespace prefixes in a depth-first fashion.

- [PSR-1][] MUST be amended to grant this PSR equal standing with [PSR-0][].


3. Narrative
------------

Given the below example implementation, and a `Foo\Bar` package of classes, one would register the path to "source" files and "unit test" files for the namespace prefix like so:

// instantiate the loader
$loader = new PackageOrientedLoader;

// register the source file paths for the namespace prefix
$loader->addNamespacePath(
'Foo\Bar',
'/path/to/Foo.Bar/src'
);

// register the unit test paths for the namespace prefix
$loader->addNamespacePath(
'Foo\Bar',
'/path/to/Foo.Bar/tests'
);

Given a package in a "sub-namespace" of `Foo\Bar\Baz\Dib`, one would register the "sub-package" like so:

$loader->addNamespacePath(
'Foo\Bar\Baz\Dib',
'/path/to/Foo.Bar.Baz.Dib/src'
);

When the autoloader calls `load()` for a fully-qualified class name of `Foo\Bar\Baz\Dib\Zim\Gir`, the implementation will search the registered paths in this order:

- first, for `/path/to/Foo.Bar.Baz.Dib/src/Zim/Gir.php`;
- then, for `/path/to/Foo.Bar/src/Baz/Dib/Zim/Gir.php`;
- last, for `/path/to/Foo.Bar/test/Baz/Dib/Zim/Gir.php`;

Note that the longest registered namespace prefix that matches the fully-qualified class name is searched first, and the shortest is searched second.


4. Example Implementation
-------------------------

The following is one possible implementation of the rules described above.

<?php
/**
* An example implementation for a package-oriented autoloader.
*/
class PackageOrientedAutoloader
{
/**
*
* An array where the key is a namespace prefix, and the value is a
* sequential array of directories for classes in that namespace.
*
* @var array
*
*/
protected $paths = array();

/**
*
* Adds a path for a namespace prefix.
*
* @param string $ns The namespace prefix.
*
* @param string $path The directory containing classes in that
* namespace.
*
* @param bool $prepend Prepend (unshift) the path onto the list of
* paths instead of appending (pushing) it.
*
* @return void
*
*/
public function addNamespacePath($ns, $path, $prepend = false)
{
$path = rtrim($path, DIRECTORY_SEPARATOR);
if ($prepend) {
array_unshift($this->paths, $path);
} else {

Beau Simensen

unread,
Apr 11, 2013, 11:02:34 PM4/11/13
to php...@googlegroups.com
On Thursday, April 11, 2013 7:00:26 PM UTC-5, pmjones wrote:
Regarding Beau Simensen's comment:

>> - Autoloader implementations MUST allow each namespace prefix to be mapped to multiple directories.
>  
> Does this need to be specified? I can see specialized PSR-X autoloader implementations that will have no need for supporting multiple directories being mapped. Would it make more sense to either drop this or change MUST to MAY?

I think it's necessary to allow it, so that users who expect to be able to map multiples using one implementation, can still do so in other implementations.

I'm not saying we should not allow it. I'm saying that we should not require every implementation to support it. Thank you for addressing my concern, though!

 

Please find the new proposal below, and let the beatings re-commence.

... 
 
- Autoloader implementations MUST allow each namespace prefix to be mapped to multiple directories.

- Autoloader implementations MUST allow directory mappings to be appended or prepended to the existing directory mappings for that namespace prefix.

Eek. A new MUST along the same lines? I think I must be misunderstanding something. :)

My stance is that I do not think that we should require any implementation to be aware of any actual mapping. Both of these MUST lines imply, at least in my mind, that an autoloader implementation has to have a state and that it has to be mutable. It doesn't say how (by way of an interface) it just vaguely says that it needs to expose that functionality.

I wrote a lot more about this (surprise, surprise) but I decided I could probably best show this by example. I would fully expect that the following (based heavily on one of Igor's autoload implementations) would qualify as a Package-Oriented Autoloader PSR implementation.

If it does qualify with the spec as written, can you explain to me how? If it does not qualify with the spec as written, is that to be expected and desired or should the spec be changed to account for these types of autoload implementations?

spl_autoload_register(function ($className) {
$prefix = 'Dflydev\\MyFancyLib\\';
$basePath = __DIR__.'/src/';
if (strncmp($prefix, $className, strlen($prefix)) === 0) {
$path = $basePath.str_replace('\\', '/', substr($className, strlen($prefix))).'.php';
if (file_exists($path)) {
require $path;
return true;
}
}
return false;
});


Larry Garfield

unread,
Apr 16, 2013, 1:05:15 AM4/16/13
to php...@googlegroups.com
Before I get into the review, some additional contextual notes:

1) This proposal popped up in a discussion of Drupal's autoloader usage, entirely without my involvement:
http://drupal.org/node/1971198

While I'd rather get a PSR approved first, I may lose that one so it looks like Drupal is probably going to go this direction either way.  I'd much rather do so in a PSR-X-compliant fashion, though.

2) In discussion in the IRC channel earlier today, two additional arguments came up that I think are relevant to why this is FIG material.

2A) Even if this "abbreviated" form was useful only for project-internal autoloading, it would still help interoperability in the "soft" sense.  That is, being able to recognize what the autoloading style was of a given project is no less useful than recognizing its spaces-vs-tabs style.  When switching to a new project, being able to recognize such things helps in shifting your brain.

2B) That said, it's still useful to individual projects.  As an example, over the weekend I released a small utility library on GitHub and Packagist.org:

https://github.com/Crell/ApiProblem

It's one class, plus an exception.  I do have src and tests directories, but even within src I have src/Crell/ApiProblem/ApiProblem.php.  Really, that's 2 directories of uselessness, which exist solely to support PSR-0 autoloading.  It's very much a library intended for reuse by other projects, not just internally by one project.

With an "abbreviated PSR-0" (what we're discussing here), I should be able to cut out those 2 directories from my repo and still have a PSR-X autoloader (which presumably would include Composer before too long) be able to automagically just work, which is exactly what we want.

There's probably lots of other very-simple libraries that could similarly benefit.  For that reason, I would argue that this proposal is very much applicable to project interoperability, just as much as PSR-0.

On with the nitpicking!
Is it really an "alternative to", or an "extension of"?  But good call pointing out that it doesn't replace PSR-0.


   Foo_Bar_Package/
       src/
           Baz.php       # Foo\Bar\Baz
       tests/
           BazTest.php   # Foo\Bar\BazTest

Additionally, since the use of underscores in class names was to represent pseudo-namespaces in PHP 4 to PHP 5.2.x, their use when namespaces proper are available is no longer necessary. This removes possible conflicts between `Foo\Bar` and `Foo_Bar`.


2. Specification
----------------

(The term "class" refers to classes, interfaces, and traits.)

- Fully-qualified class names MUST begin with a top-level namespace name, which MUST be followed by zero or more sub-namespace names, and MUST end in a class name.

- Class files MUST contain only one class definition.

- Autoloader implementations MUST map a namespace prefix to a directory.

Borrowing the language from PSR-0 would be better here, I think:

"Each namespace separator is converted to a DIRECTORY_SEPARATOR when loading from the file system."

Actually this whole section could borrow language directly from PSR-0.


- Autoloader implementations MUST allow each namespace prefix to be mapped to multiple directories.

It is not clear to me what this sentence means.


- Autoloader implementations MUST allow directory mappings to be appended or prepended to the existing directory mappings for that namespace prefix.

- Autoloader implementations MUST map the non-namespace-prefix portion of the fully-qualified class name to a sub-path by replacing namespace separators with directory separators, and MUST suffix the result with `.php`.

- Autoloader implementations MUST search for class files among their registered namespace prefixes in a depth-first fashion.

- [PSR-1][] MUST be amended to grant this PSR equal standing with [PSR-0][].

This totally does not belong in a specification. :-)  Rather, the better way of saying it would be:

"For the purposes of compliance with PSR-1, support for this specification will count equally as well as PSR-0."

That is, this spec itself clarifies/extends PSR-1.


3. Narrative
------------

Given the below example implementation, and a `Foo\Bar` package of classes, one would register the path to "source" files and "unit test" files for the namespace prefix like so:

   // instantiate the loader
   $loader = new PackageOrientedLoader;

   // register the source file paths for the namespace prefix
   $loader->addNamespacePath(
       'Foo\Bar',
       '/path/to/Foo.Bar/src'
   );

   // register the unit test paths for the namespace prefix
   $loader->addNamespacePath(
       'Foo\Bar',
       '/path/to/Foo.Bar/tests'
   );

Given a package in a "sub-namespace" of `Foo\Bar\Baz\Dib`, one would register the "sub-package" like so:

   $loader->addNamespacePath(
       'Foo\Bar\Baz\Dib',
       '/path/to/Foo.Bar.Baz.Dib/src'
   );

I just read this over twice, and I think it's all of the garbage names that are throwing me.  I can't actually parse this.  I know what we've discussed but reading this, I can't actually parse it.


When the autoloader calls `load()` for a fully-qualified class name of `Foo\Bar\Baz\Dib\Zim\Gir`, the implementation will search the registered paths in this order:

   - first, for `/path/to/Foo.Bar.Baz.Dib/src/Zim/Gir.php`;
   - then, for `/path/to/Foo.Bar/src/Baz/Dib/Zim/Gir.php`;
   - last, for `/path/to/Foo.Bar/test/Baz/Dib/Zim/Gir.php`;

Note that the longest registered namespace prefix that matches the fully-qualified class name is searched first, and the shortest is searched second.

No, the shortest is searched last. :-)
Message has been deleted

Beau Simensen

unread,
Apr 18, 2013, 11:09:26 PM4/18/13
to php...@googlegroups.com
Would this summary be a correct understanding of this PSR?
The way you worded your understanding of this PSR was hard for me to follow. I think it sounds like you have it but I'll let someone else jump in. :)

is it worth providing an interface for registering multiple mappings in one go?
This is a feature that would make sense for many PSR-X autoloaders to implement but there is no actual interface defined in this PSR. As with PSR-0, it only defines the rules by which mapping a fully qualified class name to a filesystem path should happen.


Also, does the namespace being registered need to be anything more than "\", i.e. no namespace? It sounds like this proposal could be used in legacy code that does not have any namespaces at all, so long as the PHP scripts contain only one class and the scripts are named after the class.
This proposal requires at least one level of namespace, \<Vendor>. This is in order to ensure that there are no naming collisions between packages. For example, if Zend, Symfony, and Acme each have a Cache class, by ensuring the fully qualified class name is \Zend\Cache, \Symfony\Cache, and \Acme\Cache, the classes will not clobber each other.

It would be easy to drop the requirement of the \<Vendor> namespace on the technical side of things but I think that the notion of requiring at least a vendor in the namespace something the group is not likely to change its mind on.

As far as targeting legacy code, this proposal is pretty clear on its intention of actually removing support for pre-namespace legacy code that gave PSR-0 some trouble so I think changes that will make legacy code easier to deal with are going to be a hard sell. I think other arguments would need to be made for the case of dropping the \<Vendor> requirement.


I guess taking that to its extreme, every single class within a package could have its entire namespace mapped to a physical location, and then the argument we have heard in other places that mapping namespaces directly to physical paths is restrictive, can be completely bypassed.
It sounds like you are talking about mapping each individual class. The kind of flexibility that this proposal would allow for is letting you map Acme\Controllers => app/system/controllers and would result in the class Acme\Controllers\ZimController being found at app/system/controllers/ZimController.php and Acme\Controllers\GirController being found at app/system/controllers/GirController.php.



-- 

Beau Simensen

Paul Jones

unread,
Apr 18, 2013, 11:21:17 PM4/18/13
to php...@googlegroups.com

On Apr 18, 2013, at 10:09 PM, Beau Simensen wrote:

> The kind of flexibility that this proposal would allow for is letting you map Acme\Controllers => app/system/controllers and would result in the class Acme\Controllers\ZimController being found at app/system/controllers/ZimController.php and Acme\Controllers\GirController being found at app/system/controllers/GirController.php.

I, for one, welcome our new alien autoloaders.


-- pmj

Jason Judge

unread,
Apr 19, 2013, 6:03:53 PM4/19/13
to php...@googlegroups.com


On Friday, 19 April 2013 04:09:26 UTC+1, Beau Simensen wrote:
...
is it worth providing an interface for registering multiple mappings in one go?
This is a feature that would make sense for many PSR-X autoloaders to implement but there is no actual interface defined in this PSR. As with PSR-0, it only defines the rules by which mapping a fully qualified class name to a filesystem path should happen.

My misunderstanding. I read it again, and what I thought were interfaces as a part of the spec, are actually just implementation examples.
 
Also, does the namespace being registered need to be anything more than "\", i.e. no namespace? It sounds like this proposal could be used in legacy code that does not have any namespaces at all, so long as the PHP scripts contain only one class and the scripts are named after the class.
This proposal requires at least one level of namespace, \<Vendor>. This is in order to ensure that there are no naming collisions between packages. For example, if Zend, Symfony, and Acme each have a Cache class, by ensuring the fully qualified class name is \Zend\Cache, \Symfony\Cache, and \Acme\Cache, the classes will not clobber each other.

Out of curiosity, who manages the list of vendors to make sure they are unique, i.e. that each has a single, known owner? I could grab a vendor name in packagist, and I guess that that then be mine. I could define an organisation in github, and that would be mine in that context. But is there anything to stop someone else using the same vendor name with equal feeling of ownership rights? I believe in the Java world domain names are used to identify a vendor, and it is pretty clear who owns a domain. But vendor is just a word that can be plucked from the air.
 
It would be easy to drop the requirement of the \<Vendor> namespace on the technical side of things but I think that the notion of requiring at least a vendor in the namespace something the group is not likely to change its mind on.

As far as targeting legacy code, this proposal is pretty clear on its intention of actually removing support for pre-namespace legacy code that gave PSR-0 some trouble so I think changes that will make legacy code easier to deal with are going to be a hard sell. I think other arguments would need to be made for the case of dropping the \<Vendor> requirement.


I guess taking that to its extreme, every single class within a package could have its entire namespace mapped to a physical location, and then the argument we have heard in other places that mapping namespaces directly to physical paths is restrictive, can be completely bypassed.
It sounds like you are talking about mapping each individual class. The kind of flexibility that this proposal would allow for is letting you map Acme\Controllers => app/system/controllers and would result in the class Acme\Controllers\ZimController being found at app/system/controllers/ZimController.php and Acme\Controllers\GirController being found at app/system/controllers/GirController.php.

You could also map Acme\Controllers to both app/system/controllers *and* custom-extensions/system/controllers, which could be a quite neat way of extending a package. Could it actually be used to completely replace individual classes in a package in your own custom area, I wonder, by making sure your custom area is registered first and so gets searched for class files first? That would also be kind of neat; we have template overrides in most theming systems, so why not a complete class override, where it is the best way to solve a specific issue. I like that idea.

-- Jason

na...@quicksketch.org

unread,
May 4, 2013, 8:07:38 PM5/4/13
to php...@googlegroups.com
Hi guys and girls, I'm coming over from the Drupal discussion in which we're discussing options for using (or not using) PSR-0 for our own internal plugins/modules (http://drupal.org/node/1971198). 

This proposal looks great. Have we already started a draft to get this proposal rolling? It looks like since this is an alternative to PSR-0, we can simply begin a new file in the /proposed directory. We've been calling it "PSR-X", but I'm guessing this isn't what it would actually be called. If this works essentially the same as an RFC, the next one is simply the next numeric iteration (right?), i.e. because PSR-3 (Logger interface) was the last PSR, if this were the next proposed standard it would become PSR-4. 

This situation would be similar (but not exactly) like the e-mail RFCs, where RFC 822 (http://www.ietf.org/rfc/rfc0822.txt) initially defined text-messages (e-mail) and was subsequently replaced by RFC 2822 (http://www.ietf.org/rfc/rfc2822.txt), and then again replaced by RFC 5322 (http://tools.ietf.org/rfc/rfc5322.txt). So although it's a bit disorienting because the first three PSRs are glued together (PSR-2 expands PSR-1, and PSR-1 requires namespacing of PSR-0), any new PSR should follow the numeric ordering. Basically the number only indicates the order in which the proposal was made, not the level of compliance. 

So in short, the problem of amending PSR-1 aside, can we start turning this into an official proposal, drafted in Github and work out the individual problems using the tracker? I'm new to the PHP-FIG operations; what's the next step? 

-Nate

Phil Sturgeon

unread,
May 5, 2013, 10:55:50 AM5/5/13
to php...@googlegroups.com
Hey Nate,

It's best if we keep down the number of things that could be considered controversial, but ignoring guessing the outcome of the amendments topic. It looks likely that PSR-1 will have an Errata item added, which just says "Or you can use PSR-X", which covers that.

And nope, it wont be called PSR-X, it could be PSR-4 or PSR-5, depending on if the cache proposal gets in first.

I think we need to poke Paul to convert his original text into a proposal, as we no longer have any major complaints in this thread related to the actual proposal itself.

Amy Stephen

unread,
May 5, 2013, 2:53:24 PM5/5/13
to php...@googlegroups.com
Let's see if there is a basic agreement on the problems that we are trying to solve and the alternatives.

Basic PSR-0 rules

- Namespace must start with Vendor Name.
- Physical Folders/Class File mirror the entire Namespace.
- Mixed case is allowed.

PSR-X rules

- Namespace must start with Vendor Name.
- Physical Folders do not have to mirror the entire Namespace.
- Mixed case is allowed.

Example: Acme Cache package uses Acme\Cache as its namespace. The composer.json name is defined as "name":"Acme/Cache"

I believe there are four issues people tend to complain about related to the long install paths. Do you agree these are the four problems? Did I miss something? Is there a problem listed that isn't considered a problem?

1. Composer related: adds three lowercase folders in install path.

Since these are lower case, most cannot use these nodes to resolve the namespace and the install path ends up like this:

    vendor\acme\cache\Acme\Cache\Adapter.php

Possible Solutions:

i. Composer could be modified to use the name as it is entered in the Composer.json file. Then, those folders would be available for use with the PSR-0 namespace. The install path would then be:

    vendor\Acme\Cache\Adapter.php

ii. Use lowercase values for namespace (ex. acme/cache instead of Acme/Cache). The install path would then be:

    vendor\acme\cache\Adapter.php (This is how Lithium approaches namespaces.)

iii. PSR-X Simple don't include Acme\Cache in the repository structure and instruct the class loader to start the namespace at vendor\acme\cache. Thus, the install path would then be:

    vendor\acme\cache\Adapter.php

2. Src Folder Repository Practice

Many use an approach of structuring the repository folder system using a high-level src/ folder. For those who use this approach, the namespace cannot begin until after the src folder.

Thus, the install path becomes:

    vendor\acme\cache\src\Acme\Cache

Possible solutions:

i. Add folders to isolate tests and documenation at the root folder and store source code right at the root of the package. Combined with the previous, the install path could then be:

    vendor\Acme\Cache\Adapter.php

Examples: Molajo Filesystem and Lithium Tests folder

iii. PSR-X does not directly address this. I am guessing the idea would be to not include the Acme/Cache in the folder structure, but continue with the Src folder, and if that is correct, it would have an install path like:

    vendor\acme\cache\src\Adapter.php

Question: Are there examples of the folder structure PSR-X folks are recommending? 

3. Composer target-dir adds additional folders. ex. target-dir=more\folders results in:

    vendor\acme\cache\more\folders\src\Acme\Cache

Possible solution: Don't use target-dir =)

4. Namespacing full distributions, not just packages Composer installs into the vendor folder.

Now, this is the one question that I see PSR-X addressing specifically that is not addressed above. The idea, as I understand it, would be that there is no reason to have the Acme folder to store source code that is not shared via packagist/composer. Just create your distribution folder structure, then instruct the class loader with how to load it.

So, if I want:

    plugins
    themes
    vendor/etc/we/all/understand/this
    zackstuff

I can point plugins to Molajo\Plugins namespace, and so on.

Personally, I agree with that and hacked the classloader to do exactly that (apparently tho Paul has pointed out a problem I would need to fix to avoid periods in a folder).

But - my question is - does FIG need a PSR to address namespacing for code that is not shared?

There is confusion that will result from having two namespace standards from the same body for a relatively small population. If Composer cannot be adapted, why not change PSR-0? Those who are in compliance now will still be in compliance with PSR-0 using the rules under PSR-X so there is no backwards compat issues.

So, Paul, here are my questions for you -

1. Are the four problems I identified essentially the problems your proposal aims to resolve? (If so, good, we agree on the issues.)

2. Do you see the alternatives I listed above as impossible or not appropriate to solving the problem? (If so, fine, at least the ideas were considered.)

3. Why not just adapt PSR-0 instead of adding another namespacing standard? (Do you agree there are no backwards compatability issues? And can the group agree that change in our industry is unavoidable and nothing to be worried about? ;-) ) 

I do believe it's important to get moving one way or the other on this, no sense in holding projects back.

Thanks.

Phil Sturgeon

unread,
May 5, 2013, 10:42:01 PM5/5/13
to php...@googlegroups.com
No Amy, no to everything you just said. Please don't make us start going through all of this again, this is what killed the conversation last time!

As a general comment to your entire view on this, I have to say: stop talking about Composer. This has nothing to do with Composer.

I believe there are four issues people tend to complain about related to the long install paths. Do you agree these are the four problems? Did I miss something? Is there a problem listed that isn't considered a problem?

1. Composer related: adds three lowercase folders in install path. 

See above. This is not a problem, because we're not talking about Composer. I've also never heard anybody complain about this, other than you, and I make it a point to get involved in these conversations to find out what peoples problems are. 

i. Composer could be modified to use the name as it is entered in the Composer.json file. Then, those folders would be available for use with the PSR-0 namespace. The install path would then be:
    vendor\Acme\Cache\Adapter.php

This would be mixing PSR-0 code in with classmapped code and all sorts of other random problems. I've been through this before, it doesn't work.

ii. Use lowercase values for namespace (ex. acme/cache instead of Acme/Cache). The install path would then be:

Right, we could just break everything and turn PSR-0 on its head, and still have the same problems as "i".

iii. PSR-X Simple don't include Acme\Cache in the repository structure and instruct the class loader to start the namespace at vendor\acme\cache. Thus, the install path would then be:
    vendor\acme\cache\Adapter.php

Ditto.

2. Src Folder Repository Practice 
Many use an approach of structuring the repository folder system using a high-level src/ folder. For those who use this approach, the namespace cannot begin until after the src folder.
Thus, the install path becomes: 
    vendor\acme\cache\src\Acme\Cache

This is not a problem, so it needs no solutions. Folks have been putting their code in src folders since before man landed on the moon. 

iii. PSR-X does not directly address this. I am guessing the idea would be to not include the Acme/Cache in the folder structure, but continue with the Src folder, and if that is correct, it would have an install path like:
    vendor\acme\cache\src\Adapter.php

YES! This bit. This is a valid example. 

vendor\acme\cache\src\Adapter.php = Acme\Cache\Adapter

Composer is still exactly the same as always (because we're not talking about Composer), people can still use a src folder if they like (because why the heck would they want to shove their tests and metadata in together) and a little config can shove Acme\Cache towards src/ itself. 

3. Composer target-dir adds additional folders. ex. target-dir=more\folders results in: 
    vendor\acme\cache\more\folders\src\Acme\Cache
Possible solution: Don't use target-dir =)

Again your proposing solutions to problems that don't exist. "Oh no, I have the flexibility to mount my namespace to a sub-dir if I want to, how terrible!" 

4. Namespacing full distributions, not just packages Composer installs into the vendor folder.
Now, this is the one question that I see PSR-X addressing specifically that is not addressed above. The idea, as I understand it, would be that there is no reason to have the Acme folder to store source code that is not shared via packagist/composer. Just create your distribution folder structure, then instruct the class loader with how to load it. 

I don't know what this is.

But - my question is - does FIG need a PSR to address namespacing for code that is not shared? 

An autoloading standard can be used for anything. I can have an application that uses PSR-0 to autoload shared code which is not from composer, but copied and pasted from some other application. Thats AWESOME, and thats the goody that PSR-0 gives us.

Now, PSR-X would not be quite so easy to copy and paste around, because it relies on a little metadata. BECAUSE people use Composer a lot, PSR-X will allow us to bake that metadata requirement into the autoloader, just like the composer.json already does, but interacting with the ClassLoader would let people handle this metadata programatically too. 

This means we ARE working on namespacing standards for sharing code, and always have been. When folks talk about namespacing non-shared code like in Drupal and PyroCMS then thats just fine too. Autoloading is autoloading, and you should not focus such attention on Composer as it is just one specific implementation.

There is confusion that will result from having two namespace standards from the same body for a relatively small population. If Composer cannot be adapted, why not change PSR-0? Those who are in compliance now will still be in compliance with PSR-0 using the rules under PSR-X so there is no backwards compat issues. 

PSR-X will likely be very quickly adopted by the majority of developers because it knocks some superfluous namespaces out of the way and drops the _ support, which can lead to problems. There will be a little confusion no doubt, but there always is. A few blog posts here and there and a bit on the FAQ will help just fine, but those developers who care will know where to look, and those that dont will just complain on reddit. We can't hold off doing something useful based on potential complaints from the entire internet.

So, Paul, here are my questions for you - 

I'm going to answer these, because I know Paul is busy working on making this into a pull request, and most likely doesn't have time to go point to point on this stuff. Paul: you should totally correct me if im wrong.

1. Are the four problems I identified essentially the problems your proposal aims to resolve? (If so, good, we agree on the issues.)

None of the 4 things you said are problems.

2. Do you see the alternatives I listed above as impossible or not appropriate to solving the problem? (If so, fine, at least the ideas were considered.)

Drastically changing PSR-0 in any way, or changing Composer to force the assumption that everything is PSR-0 is going to cause more confusion than adding a secondary optional autoloader. I don't think anyone on the FIG or Composer teams will be interested in that route, but again people should definitely correct me if im wrong on that. 

3. Why not just adapt PSR-0 instead of adding another namespacing standard? (Do you agree there are no backwards compatability issues? And can the group agree that change in our industry is unavoidable and nothing to be worried about? ;-) )  

Same as above. We're barely able to get an Errata or "Trivial Change" into PSR-0, nobody is going to drastically change this to make PSR-0.1 or PSR-0v2  or whatever, why not just make PSR-4 to replace it? That is considerably less confusing.

I do believe it's important to get moving one way or the other on this, no sense in holding projects back.

Absolutely, if we hold this up any longer Drupal 8 is going to miss their change to get PSR-X included, which will be a MASSIVE shame. Please do not kill this conversation again with more talk of PSR-0ing the Composer vendor names, or any of the stuff that we have discussed multiple times before.

I'm sure you'll not be happy with this response, but im not sat here blindly telling you are wrong, I'm telling you that your understanding of the problems are wrong and your suggestions cause more problems than they would ever solve.

This autoloader is super-simple, and solves a few issues, which is awesome. We need to get it going ASAP so we can start using it, then I can write up a few blogs for a few sites explaining what its all about so everyone is nice and happy and on the same page when it gets voted in.

Optional autoloader > mutilating existing standards and projects.

Larry Garfield

unread,
May 6, 2013, 1:21:53 AM5/6/13
to php...@googlegroups.com
Let me try to simplify even further:

PSR-X: Same as PSR-0, but with the following additions:
1) Underscores in class names have no special meaning or processing.
2) You may optionally specify a point within the fully qualified name of a class where the directory mapping starts, rather than it always being at the start of the name.  How you specify that is, I suppose, up to the implementation.  (In composer.json it would probably be a property in the autoloader block.)

That is the entirety scope we're discussing.  Let's not creep it.

Phil, Paul, does that match your understanding?

--Larry Garfield
--
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/-/iuvsAYuW9MgJ.

Phil Sturgeon

unread,
May 6, 2013, 8:52:13 AM5/6/13
to php...@googlegroups.com
It matches my understanding perfectly. Thanks Larry.

Daniel Ribeiro

unread,
May 6, 2013, 8:59:24 AM5/6/13
to php...@googlegroups.com
This chick is on FIRE!


Daniel Ribeiro Gomes Pereira
iPhone: +55 (48) 9111-0931


2013/5/6 Phil Sturgeon <em...@philsturgeon.co.uk>
It matches my understanding perfectly. Thanks Larry.

--
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/-/xeI6-q0bhcAJ.

Paul M. Jones

unread,
May 6, 2013, 12:27:34 PM5/6/13
to php...@googlegroups.com

On May 6, 2013, at 12:21 AM, Larry Garfield wrote:

> Let me try to simplify even further:
>
> PSR-X: Same as PSR-0, but with the following additions:
> 1) Underscores in class names have no special meaning or processing.
> 2) You may optionally specify a point within the fully qualified name of a class where the directory mapping starts, rather than it always being at the start of the name. How you specify that is, I suppose, up to the implementation. (In composer.json it would probably be a property in the autoloader block.)
>
> That is the entirety scope we're discussing. Let's not creep it.
>
> Phil, Paul, does that match your understanding?

I would argue that we need a little more detail around it, but yes, that's the core. I'll see if I can trim back the proposal some and make it more formal.


-- pmj

Larry Garfield

unread,
May 6, 2013, 12:53:12 PM5/6/13
to php...@googlegroups.com
I wonder if we need to specify a way to define what that root is other
than "we expect Composer will take care of this".

--Larry Garfield

Paul Jones

unread,
May 6, 2013, 12:56:51 PM5/6/13
to php...@googlegroups.com
I don't think so; the root is arbitrary, and may be different for each package.


-- pmj

Beau Simensen

unread,
May 6, 2013, 1:09:09 PM5/6/13
to php...@googlegroups.com
I think I'd be more happy if Composer wasn't mentioned in any way, actually.

I think it would be great if PSR-X followed in PSR-0 footsteps and
only defined the transformation rules and provided a handful of
examples in the form of:

Given class Acme\Whizbang\Widget\ThingFactory and a properly
configured PSR-X autoloader mapping Acme\Whizbang to
/path/to/acme-whizbang/src, the class would be found at
/path/to/acme-whizbang/src/Widget/ThingFactory.php

We can provide examples going deeper and shallower and we can provide
examples with and without src/ or lib/ type directories.

Maybe we can represent it with a table or something.

If there are example implementations in the doc itself, they should
perhaps be limited to just how to do the transformation rules and not
a complete class loading implementation.

Paul Jones

unread,
May 6, 2013, 2:48:43 PM5/6/13
to php...@googlegroups.com
All,

I have added a formal proposal document here:

<https://github.com/php-fig/fig-standards/blob/master/proposed/package-oriented-autoloader.md>

I have stripped it down somewhat from the preliminary version.

On May 6, 2013, at 12:09 PM, Beau Simensen wrote:

> I think it would be great if PSR-X followed in PSR-0 footsteps and
> only defined the transformation rules and provided a handful of
> examples in the form of:
>
> Given class Acme\Whizbang\Widget\ThingFactory and a properly
> configured PSR-X autoloader mapping Acme\Whizbang to
> /path/to/acme-whizbang/src, the class would be found at
> /path/to/acme-whizbang/src/Widget/ThingFactory.php
>
> We can provide examples going deeper and shallower and we can provide
> examples with and without src/ or lib/ type directories.
>
> Maybe we can represent it with a table or something.
>
> If there are example implementations in the doc itself, they should
> perhaps be limited to just how to do the transformation rules and not
> a complete class loading implementation.

/me nods

I can see where that'd be a useful alternative to the existing proposal language. However, I am unable to determine that language at this time; if you can come up with something, that'd be a great help.

Aside from that, there appears to be no widely-shared substantive disagreement with the body of the proposal. Pending this possible alternative example language, I will call for votes in the next couple days.


-- pmj

Beau Simensen

unread,
May 6, 2013, 3:12:02 PM5/6/13
to php...@googlegroups.com
<https://github.com/php-fig/fig-standards/blob/master/proposed/package-oriented-autoloader.md>
This appears to be added directly to the fig-standard repo instead of a PR. Was this intended? If so, how would you like for us to contribute changes?


I would suggest moving the example directory structures from Overview into the bottom of Narrative after the PHP example showing a fictional autoloader implementation. Showing it earlier just shows the end result without the why and I think it might be confusing. I can see people looking at that wondering how the mapping happens and why are foo/bar lowercase when the namespaces are Foo\Bar? Showing the end result after showing how the autoloader is setup will help keep things more clear.


I think the Overview could be updated to be a bit more descriptive, especially if the example section is moved to the Narrative.

This PSR is intended as an alternative to, not a replacement for, PSR-0. It removes some legacy compatibility features that were built into PSR-0 (specifically how _ are handled) and it allows for classes to map to directory structures that are less artificially deep than PSR-0 required.


Would it be worthwhile to add base directory or root directory or something along those lines to the definitions? We talk about PSR-0 "roots" and in this proposal there is some talk about a "base directory", but that is never really defined.

base directory: The physical path on disk from which filenames based on non-namespace prefixed are rooted.

I have no idea how to word it, exactly, but I think it is worth bringing up for discussion.



All in all, I like it. :)

Phil Sturgeon

unread,
May 6, 2013, 5:15:59 PM5/6/13
to php...@googlegroups.com
This PSR is intended as an alternative to, not a replacement for, PSR-0. It removes some legacy compatibility features that were built into PSR-0 (specifically how _ are handled) and it allows for classes to map to directory structures that are less artificially deep than PSR-0 required.

+1 for this text. I was trying to think up something to make it more fish-slappingly obvious and this covers it nicely.

Otherwise, its really tough to see whats happening - especially with the end-results first as you say.

Paul Jones

unread,
May 6, 2013, 7:48:28 PM5/6/13
to php...@googlegroups.com

On May 6, 2013, at 2:12 PM, Beau Simensen wrote:

>> <https://github.com/php-fig/fig-standards/blob/master/proposed/package-oriented-autoloader.md>
> This appears to be added directly to the fig-standard repo instead of a PR. Was this intended? If so, how would you like for us to contribute changes?

Oy -- my bad. Well, it's there now; if everyone's amenable to it, just issue PRs against from there (or add inline comments at github, or comment here).


> I would suggest moving the example directory structures from Overview into the bottom of Narrative after the PHP example showing a fictional autoloader implementation. Showing it earlier just shows the end result without the why and I think it might be confusing. I can see people looking at that wondering how the mapping happens and why are foo/bar lowercase when the namespaces are Foo\Bar? Showing the end result after showing how the autoloader is setup will help keep things more clear.

I have moved it out of Overview and into Narrative, but it's in the middle instead of at the end. It seems to me the directory structure is a prerequisite for determining the params for the autoloader calls.


> I think the Overview could be updated to be a bit more descriptive, especially if the example section is moved to the Narrative.
>
>> This PSR is intended as an alternative to, not a replacement for, PSR-0. It removes some legacy compatibility features that were built into PSR-0 (specifically how _ are handled) and it allows for classes to map to directory structures that are less artificially deep than PSR-0 required.

Done, with some modifications.


> Would it be worthwhile to add base directory or root directory or something along those lines to the definitions? We talk about PSR-0 "roots" and in this proposal there is some talk about a "base directory", but that is never really defined.
>
> base directory: The physical path on disk from which filenames based on non-namespace prefixed are rooted.
>
> I have no idea how to word it, exactly, but I think it is worth bringing up for discussion.

Also done, with some modifications.


> All in all, I like it. :)

Joy!


-- pmj

Phil Sturgeon

unread,
May 6, 2013, 8:48:19 PM5/6/13
to php...@googlegroups.com
This looks excellent, bar the duplicate line. So, whats next to get more feedback from the group? 

Paul Jones

unread,
May 6, 2013, 9:05:17 PM5/6/13
to php...@googlegroups.com

On May 6, 2013, at 7:48 PM, Phil Sturgeon wrote:

> This looks excellent, bar the duplicate line. So, whats next to get more feedback from the group?

Man, I think we give it a day or two and call for votes; we can let the "amending" process work itself out in the mean time.


-- pmj

Nathan Haug

unread,
May 7, 2013, 1:26:27 AM5/7/13
to php...@googlegroups.com
Some minor feedback:
> fully-qualified class name (FQCN): An absolute namespace and class name; e.g., Foo\Bar\Dib\Zim. The namespace portion is Foo\Bar\Dib and the class portion is Zim.
This definition uses "e.g. Foo\Bar\Dib\Zim…" for its example, but the subsequent definitions use "Given a FQCN of Foo\Bar\Dib\Zim…". Can we use the "Given…" syntax for this definition to make it match the others?

> Fully-qualified class names MUST begin with a top-level namespace name, which MUST be followed by zero or more sub-namespace names, and MUST end in a class name.
There are two mentions to "namespace names" in this sentence, but a namespace name is not in the list of definitions. Could this definition be added (either as a separate definition or part of the FQCN definition)?

`namespace name`: An individual part of the `namespace portion` of the `FQCN`. Given a FQCN of ``Foo\Bar\Dib\Zim``, the individual namespace names are ``Foo``, ``Bar``, and ``Dib``.

Or if we can rephrase this requirement to avoid "namespace name" term entirely that would be an alternative.

I initially thought that "MUST be followed by zero or more sub-namespace names" should be "MAY be followed by one or more sub-namespace names". But since PSR-X loaders would be required to support "zero or more", it makes this requirement non-optional. Therefor MUST seems like the right terminology according to RFC 2119 (http://tools.ietf.org/html/rfc2119).

The PSR makes sense to me and it's easy to understand. The examples are clear and benefit from the brevity. Thanks so much for drafting this Paul.

--
Nathan Haug
Sent with Sparrow (http://bit.ly/sigsprw)
> --
> 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 (mailto:php-fig+u...@googlegroups.com).
> To post to this group, send email to php...@googlegroups.com (mailto:php...@googlegroups.com).

Jason Judge

unread,
May 7, 2013, 5:13:55 AM5/7/13
to php...@googlegroups.com


On Monday, May 6, 2013 8:12:02 PM UTC+1, Beau Simensen wrote:
... 
I think the Overview could be updated to be a bit more descriptive, especially if the example section is moved to the Narrative.

This PSR is intended as an alternative to, not a replacement for, PSR-0. It removes some legacy compatibility features that were built into PSR-0 (specifically how _ are handled) and it allows for classes to map to directory structures that are less artificially deep than PSR-0 required.
...

One term I would question in here is "artificially deep". What does that mean?

So far as I can see, it means that lower (from the root) namespaces that contain no class files, can be skipped. How many levels that is, will depend on the package. For most composer packages that will be two levels. For some projects that may be three or more levels. For an internal (not-published) library it may be that no levels can be skipped because there are classes right at the root.

What it means though, I don't see how any of those namespace levels are "artificial", and I don't think that word is necessarily going to explain to people who don't already know what it means, how it works.

-- Jason

Paul Jones

unread,
May 7, 2013, 8:56:51 AM5/7/13
to php...@googlegroups.com

On May 7, 2013, at 4:13 AM, Jason Judge wrote:

>
>
> On Monday, May 6, 2013 8:12:02 PM UTC+1, Beau Simensen wrote:
>> ...
>> I think the Overview could be updated to be a bit more descriptive, especially if the example section is moved to the Narrative.
>>
>> This PSR is intended as an alternative to, not a replacement for, PSR-0. It removes some legacy compatibility features that were built into PSR-0 (specifically how _ are handled) and it allows for classes to map to directory structures that are less artificially deep than PSR-0 required.
>> ...
>
> One term I would question in here is "artificially deep". What does that mean?

I have already remedied that to use "shallower." See the updated version here:

<https://github.com/php-fig/fig-standards/blob/master/proposed/package-oriented-autoloader.md>


-- pmj

Amy Stephen

unread,
May 7, 2013, 9:55:47 AM5/7/13
to php...@googlegroups.com

On Monday, May 6, 2013 12:21:53 AM UTC-5, Larry Garfield wrote:
Let me try to simplify even further:

PSR-X: Same as PSR-0, but with the following additions:
 
Exactly - PSR-0 fits into PSR-X. So, why not just amend the standard since everyone who is PSR-0 compliant would be PSR-X complaint.
 
1) Underscores in class names have no special meaning or processing.

So, keep that rule in the amendment.
 
2) You may optionally specify a point within the fully qualified name of a class where the directory mapping starts, rather than it always being at the start of the name.  How you specify that is, I suppose, up to the implementation.  (In composer.json it would probably be a property in the autoloader block.)

PSR-0 fits into this. You just start at the beginning of the string. This is the only real change.

Then, there is just one namespace rule. What folks are after is shortening the install path by starting the namespace within the string. Fine. But is there really a reason for a new standard?


 

Amy Stephen

unread,
May 7, 2013, 9:56:19 AM5/7/13
to php...@googlegroups.com
My gender has no bearing on this discussion.

Igor Wiedler

unread,
May 7, 2013, 10:16:10 AM5/7/13
to php...@googlegroups.com
On Tuesday, May 7, 2013 3:55:47 PM UTC+2, Amy Stephen wrote:

Exactly - PSR-0 fits into PSR-X. So, why not just amend the standard since everyone who is PSR-0 compliant would be PSR-X complaint.

Amending PSR-0 in such a way is not really an option, and I believe this has been discussed quite a bit already. One long discussion took place on the PHP town hall podcast[0].

It introduces one of two cases.

a) The new rules are mandatory, which means every existing PSR-0 implementation is no longer compliant until it adds support for the new stuff.

b) The new rules are optional, which means that you now have to implement "PSR-0 with optional extensions" which might as well be PSR-n.

Either way, it introduces this huge problem of "PSR-0 before they changed it" vs "PSR-0 after they changed it" which really will do more harm than good. What exactly is the issue with making a new "standard"? Look at the number of PEPs [1] or RFCs [2] (warning: huge page, will take ages to load).

Not seeing the problem.

Regards,

Igor


Jordi Boggiano

unread,
May 7, 2013, 11:37:04 AM5/7/13
to php...@googlegroups.com
> 1) Underscores in class names have no special meaning or processing.
>
>
> So, keep that rule in the amendment.

Actually this rule sucks because it forces the autoloader to do more
work than strictly needed. So as Composer maintainer I'm happy to see it
go away for PSR-X packages.

Cheers

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

Amy Stephen

unread,
May 7, 2013, 12:19:51 PM5/7/13
to php...@googlegroups.com
Jordi - if I understand correctly, weren't the underscores added for Zend Framework? And, if I am not mistaken, I believe that exception is no longer needed. Is that correct? It would be good to hear if those exceptions are still needed, or not.


On Tuesday, May 7, 2013 9:16:10 AM UTC-5, Igor Wiedler wrote:
On Tuesday, May 7, 2013 3:55:47 PM UTC+2, Amy Stephen wrote:

Exactly - PSR-0 fits into PSR-X. So, why not just amend the standard since everyone who is PSR-0 compliant would be PSR-X complaint.

Amending PSR-0 in such a way is not really an option, and I believe this has been discussed quite a bit already. One long discussion took place on the PHP town hall podcast[0].

It introduces one of two cases.

a) The new rules are mandatory, which means every existing PSR-0 implementation is no longer compliant until it adds support for the new stuff.

What new stuff? PSR-X reduces the requirements, it does not add requirements.
 

Not seeing the problem.

Can it be clearly stated when one would choose PSR-0 over PSR-X?

Paul Jones

unread,
May 7, 2013, 12:26:55 PM5/7/13
to php...@googlegroups.com

On May 7, 2013, at 11:19 AM, Amy Stephen wrote:

> if I understand correctly, weren't the underscores added for Zend Framework?

Using underscores was a common practice for representing namespaces (technically pseudo namespaces) that arose out of Horde/PEAR conventions in wide use at the time. Zend, Solar, and various library projects used them for that purpose. They weren't "added" so much as "recognized as the common practice."


-- pmj

Brett Bieber

unread,
May 7, 2013, 12:41:35 PM5/7/13
to php...@googlegroups.com
My recollection is concurrent with Paul's. It was recognized as common-practice.

--
Brett Bieber

Beau Simensen

unread,
May 7, 2013, 2:47:16 PM5/7/13
to php...@googlegroups.com
I'm still of the mindset that we should consider removing the example implementation from the spec. I was willing to just let it go, but then I saw a lot of chatter about PSR-0, the example code, and the linked reference implementation today. It makes me feel like maybe I was giving up too easily on this subject as it is showing that example implementations can have the potential to lead to problems long into the future. :)

I think that the language in PSR-X is already less restrictive than the PSR-0 language ("this is one example" vs. "this is the current recommended way..."), but maybe we can do more to guard against future issues and complains that may come up because of code embedded in the spec? I'm not sure what this would look like, but maybe we can work through some ideas?

Things I'm hoping this will avoid:

 * If the example cannot do it, some people may decide that the spec does not cover the situation
 * If the example can do it, some people may decide that in order to be compatible they must do everything in the example
 * If the example results in actual errors at some point it would be great to not have known broken code hanging around for the public to tear to pieces


Some of the potential impact may be limited if we can have the ability to amend PSR-X (and PSR-0) in some way, via errata or whatever. So maybe it isn't a huge deal? I'd still like to discuss it a little more before finalizing it though.

Beau Simensen

unread,
May 7, 2013, 3:02:09 PM5/7/13
to php...@googlegroups.com
Does the Specification section need to discuss the priority in which namespaces should be checked?

For example, If Foo\Bar\Gir and Foo\Bar are both mapped, which should be checked first for Foo\Bar\Gir\Dib? I would assume (based on experience with Composer and a handful of other PSR-0 class loaders) that the most specific paths should be checked first ( Foo\Bar\Gir should be checked first, and then Foo\Bar if it is not found... ).

I know this was discussed before. I don't know where we landed on it. But as far as I can see, it isn't in PSR-X currently. I want to make sure that was intentional and not an oversight.

Maybe this is an implementation detail. And maybe it doesn't really matter since it is possible to have more than one class loader registered. But if anyone *does* think it is important, I think it should be specified explicitly.

Paul Jones

unread,
May 7, 2013, 3:03:57 PM5/7/13
to php...@googlegroups.com

On May 7, 2013, at 2:02 PM, Beau Simensen wrote:

> Does the Specification section need to discuss the priority in which namespaces should be checked?

It was intentionally removed, in the interest of stripping down to essentials (a la PSR-0).


-- pmj

Paul Jones

unread,
May 7, 2013, 3:07:26 PM5/7/13
to php...@googlegroups.com

On May 7, 2013, at 1:47 PM, Beau Simensen wrote:

> I'm still of the mindset that we should consider removing the example implementation from the spec.
...
> I'm not sure what this would look like, but maybe we can work through some ideas?

I don't know what it would look like, either. I get the feeling this is a "damned if you do, damned if you don't" situation. If the example is there, then people will nitpick it. If the example is not there, people will say the PSR is confusing and they need an example. I say having it there is useful, but I am willing to see it stripped down further than it is now.


-- pmj

Phil Sturgeon

unread,
May 7, 2013, 3:16:31 PM5/7/13
to php...@googlegroups.com
I think we need the sample implementation in there. 

Folks like Anthony Ferrera are very quick to complain that PSR-0 is broken based on the "sample SplClassLoader implementation", so having stronger wording that this is not ACTUALLY THE SPEC and other autoloaders can add their own super-set features should cover it.

Beau Simensen

unread,
May 7, 2013, 4:48:14 PM5/7/13
to php...@googlegroups.com
Should there be another line for the Specification section dealing with how to handle the case where the file does not exist for a given prefix? It may be obvious, but it seems like it might be good to be clear on? Maybe not this exactly, but something along these lines:

Implementations MUST NOT cause errors if a file for the requested fully-qualified class name cannot be found.



Paul Jones

unread,
May 7, 2013, 4:59:26 PM5/7/13
to php...@googlegroups.com

On May 7, 2013, at 2:16 PM, Phil Sturgeon wrote:

> I think we need the sample implementation in there.
>
> Folks like Anthony Ferrera are very quick to complain that PSR-0 is broken based on the "sample SplClassLoader implementation", so having stronger wording that this is not ACTUALLY THE SPEC and other autoloaders can add their own super-set features should cover it.

Here's a more stripped-down version of the example which (among other things) uses the terminology of the spec. Thoughts?


<?php
namespace PsrExample;

/**
*
* An example implementation for a package-oriented autoloader. Note that this
* is only an example, and is not a specification in itself.
*
*/
class PackageOrientedAutoloader
{
/**
*
* An array where the key is a namespace prefix, and the value is a
* a base directory for classes in that namespace.
*
* @var array
*
*/
protected $prefix_base = array();

/**
*
* Sets the base directory for a namespace prefix.
*
* @param string $prefix The namespace prefix.
*
* @param string $base The directory containing classes in that
* namespace.
*
* @return void
*
*/
public function setNamespacePrefixBase($prefix, $base)
{
$base = rtrim($base, DIRECTORY_SEPARATOR);
$this->prefix_base[$prefix] = $base;
}

/**
*
* Loads the class file for a fully qualified class name.
*
* @param string $fqcn The fully-qualified class name.
*
* @return bool True if loaded, false if not.
*
*/
public function load($fqcn)
{
// the non-namespace-prefix portion of the fully-qualified class name
$nnsp = '';

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

// take the last element off the FQCN parts, and add to the
// non-namespace-prefix, representing a partial file name.
$nnsp = $nnsp . DIRECTORY_SEPARATOR . array_pop($parts);

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

// is there a base for this namespace prefix?
if (isset($this->prefix_base[$prefix])) {

// yes. create a complete file name from the namespace dir
// and partial name
$file = $this->prefix_base[$prefix] . $nnsp . '.php';

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

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

/**
*
* Uses `require` to read a file from the filesystem.
*
* @param string $file
*
* @return bool True if the file gets read; false if it does not.
*
*/
protected function readFile($file)
{
if (! is_readable($file)) {
return false;
}

require $file;
return true;
}
}




-- pmj

Paul Jones

unread,
May 7, 2013, 5:00:50 PM5/7/13
to php...@googlegroups.com

On May 7, 2013, at 3:48 PM, Beau Simensen wrote:

> Should there be another line for the Specification section dealing with how to handle the case where the file does not exist for a given prefix? It may be obvious, but it seems like it might be good to be clear on? Maybe not this exactly, but something along these lines:
>
> Implementations MUST NOT cause errors if a file for the requested fully-qualified class name cannot be found.

I don't know; I think it's fair for a project-specific autoloader to be the last resort for that project, and throw an exception or raise an error if the file is not found.


-- pmj

Beau Simensen

unread,
May 7, 2013, 5:06:49 PM5/7/13
to php...@googlegroups.com
I worked on the following and can also be found here https://gist.github.com/simensen/3ea9322311644cc275e6 The wording around it could maybe use some work, but mostly wanted to show it getting cut down a lot from its current form.

I really like the idea of putting something minimal in the spec as opposed to a more fully functional class loader. This example shows all that really needs to be shown, mostly how the things interact with each other. We can then leave the other stuff up to the specific implementations like how to handle multiple namespaces, how to handle multiple paths for the same namespace, etc.

It looks like Paul had the same idea to try and use the spec terminology. I think it is a good idea. :)



The following is an example of a hypothetical project-specific PSR-X compatible autoloader. It illustrates how afully-qualified class name should interact with a namespace prefix and a base directory in order to determine the location of the file containing the requested class, interface, or trait.

<?php

// Given a PHP file named /path/to/project/example.php with the following
// content:
spl_autoload_register(function ($fqcn) {
    $namespacePrefix = 'Foo\Bar';
    $baseDirectory = __DIR__.'/src/';
    if (0 === strncmp($namespacePrefix, $fqcn, strlen($namespacePrefix))) {
        $nonNamespacePrefix = substr($fqcn, strlen($namespacePrefix));
        $nonNamespaceFilename = str_replace('\\', '/', $nonNamespacePrefix).'.php';
        $path = $baseDirectory.$nonNamespaceFilename;
        if (file_exists($path)) {
            require $path;
            return true;
        }
    }
    return false;
});

// On calling the following line, the PSR-X compatible autolaoder registered
// above would attempt to load the FQCN from /path/to/project/src/Dib/Zim.php
new Foo\Bar\Dib\Zim;

This SHOULD NOT be seen as anything more than an example implementation of the PSR-X Specification. PSR-X class loaders MAY contain additional features and may differ in how they are implemented. As long as a class loader adheres to the rules set forth in the Specification they MUST be considered PSR-X compatible.





Larry Garfield

unread,
May 7, 2013, 5:31:58 PM5/7/13
to php...@googlegroups.com
If the class isn't found, PHP will already fatal for you as it should.
Unless it's a class_exists() call, in which case fataling or
exception-ing is always wrong. But you can't tell which is which from
the autoloader. An autoloader that actively dies on not-found is
breaking the autoloader contract from PHP, not FIG.

Which may be an argument that we don't need to mention it, actually. :-)

--Larry Garfield

Amy Stephen

unread,
May 7, 2013, 5:44:58 PM5/7/13
to php...@googlegroups.com
Brett and Paul -

Is the underscore issue behind us, now? Rereading Paul's first post, sounds like since 5.2, maybe this approach is no longer needed? Are projects adapting? Or, is PSR-0 essentially needed for that purpose until those migrations have taken place?

Still trying to see why two namespace standards are needed.


Paul -

Is this basically correct? 

PSR-X requires two things:
1) A distinct high-level qualifier (ex. 'Aura', 'Drupal', 'Molajo');
2) The class must be contained within a file by itself, where the file is named the same as the class, with a .php extension. 

Asked differently, would resolving this namespace: Foo\Bar\Adapter, as follows, be compliant?

    $loader->addNamespacePath( 
        'Foo\Bar', 
        '/path/to/Wherever/I/Want/To/Put/It/Adapter.php' 
    ); 

Personally, I don't believe it's necessary or helpful to provide examples of a classloader. Just clarify the rules a developer requires to write a classloader, and do so as minimally as possible. 

+++

I also think it would be helpful to have Anthony, or others who struggled with PSR-0, to look at PSR-X and make sure they feel good about it. Hopefully, his concerns are addressed. 


Phil Sturgeon

unread,
May 7, 2013, 6:53:14 PM5/7/13
to php...@googlegroups.com

Is the underscore issue behind us, now? Rereading Paul's first post, sounds like since 5.2, maybe this approach is no longer needed? Are projects adapting? Or, is PSR-0 essentially needed for that purpose until those migrations have taken place?

Yep, no need to keep supporting that. Hello PHP 5.3.
 
Still trying to see why two namespace standards are needed.

Because PSR-0 is set in stone, and changing it would break things for current people. If we say "And boom, _ is gone" then that breaks things for everyone. Much confusion.
 
Is this basically correct? 

PSR-X requires two things:
1) A distinct high-level qualifier (ex. 'Aura', 'Drupal', 'Molajo');

Yep.
 
Asked differently, would resolving this namespace: Foo\Bar\Adapter, as follows, be compliant?

    $loader->addNamespacePath( 
        'Foo\Bar', 
        '/path/to/Wherever/I/Want/To/Put/It/Adapter.php' 
    ); 


Kinda,
 
    $loader->addNamespacePath( 
        'Foo\Bar', 
        '/path/to/Wherever/I/Want/To/Put/It' 
    );  
 
I also think it would be helpful to have Anthony, or others who struggled with PSR-0, to look at PSR-X and make sure they feel good about it. Hopefully, his concerns are addressed. 

I tried this on the PHP Town Hall but it kicked off an argument about how functions are not part of the spec...

Are your concerns addressed? 

Amy Stephen

unread,
May 7, 2013, 7:31:43 PM5/7/13
to php...@googlegroups.com


On Tuesday, May 7, 2013 5:53:14 PM UTC-5, Phil Sturgeon wrote:

Is the underscore issue behind us, now? Rereading Paul's first post, sounds like since 5.2, maybe this approach is no longer needed? Are projects adapting? Or, is PSR-0 essentially needed for that purpose until those migrations have taken place?

Yep, no need to keep supporting that. Hello PHP 5.3.

OK, so that's the only piece of PSR-0 that PSR-x doesn't cover.
 
 
Still trying to see why two namespace standards are needed.

Because PSR-0 is set in stone, and changing it would break things for current people. If we say "And boom, _ is gone" then that breaks things for everyone. Much confusion.


Is PSR-x backward compatible to PSR-0 (with the exception of the underscore issue?)

If so, nothing will break. 

 
 
Is this basically correct? 

PSR-X requires two things:
1) A distinct high-level qualifier (ex. 'Aura', 'Drupal', 'Molajo');

Yep.

PSR-0 users are already compliant then.


Are your concerns addressed? 

I'd like to see one namespace standard, not two. 

Essentially, what I hear PSR-X saying is that it's about a high-level vendor space. That's sufficient to address interoperability. It gets away from anything Composer, or how the repository is structured, or requiring any physical mapping of folders and files to namespaces, so the length of the install path issue, which is what has been bothersome to folks, can be set aside. That's all good and I fully support that. 

But - one namespace standard, please. Deal with it, don't avoid it, please. Over the long run, that is what will help this issue become less confusing. Let's put this forever behind us. =)

I'll ping Anthony and see if he sees any issues with PSR-x. He doesn't have to approve it, but he's a very smart guy and it would be helpful to have his support. In a way, that's why avoiding the code aspect is helpful. Just explain (and discuss) the rules. Lots of ways to skin a cat. 

Thanks Phil.
It is loading more messages.
0 new messages