[RFC] Classpath Resources / Resource Locator direction

206 views
Skip to first unread message

Beau Simensen

unread,
Dec 6, 2013, 1:21:54 PM12/6/13
to php...@googlegroups.com
Hi all! Now that PSR-4 is passed I can talk about this again without people thinking I'm trying to derail PSR-4. ;)

There are probably other paths we can follow as well, but I've listed three potential options for how to move forward with the idea of some sort of resource location stuff for (a|) future possible PSR(s).



Classpath Resources

This PSR proposes the use of autoloader configuration metadata as a means for addressing resources that may represent any type of file.

The general idea here being that we add the notion of a classpath to PHP. Prior art on this would be Spring Framework's ability to access non-class resources using the same conventions you would you to "find" a Java class.

In short, this would add "classpath" to the vocabulary of PHP developers and give it meaning. I've worked on a few ideas for this. Here is one of them:


Simple PSR-4 based examples:

Given a classpath comprised of a PSR-4 configuration with a namespace prefix Foo\Bar and a directory src, the following is an example of addressing namespaced resources:

    \Foo\Bar\Baz\Qux.php => src/Baz/Quz.php
    \Foo\Bar\Resources\config\services.json => src/Resources/config/services.json
    \Foo\Bar\Resources\public\logo.png => src/Resources/public/logo.png


I'd really like to see this concept represented as a standalone idea/concept. It would allow developers to take this concept and run with it. For example, Bernhard already took this basic idea and created some really cool higher level concepts on top of this underlying idea. What else could people come up with if they started to play with these ideas?

There would be a relatively low barrier to entry. Implementing this at the autoloader level would be pretty trivial. The concept is super simple and people can start working with it right away. This was a huge deal in any discussion of including resource location in PSR-4... people were adamant about being able to be a classloader without having to be a resource locator. Likewise, I'd like people to be able to build simple solutions based on autoloader metadata without requiring people to implement a full fledged resource locator.

One of the downsides I've heard about this approach is that there is no "API" for using it. With autoloaders, the autoloader is the way that you would interact with this. How will anyone use this? Why would Drupal, Laravel, or Symfony care? Just saying something is possible is not terribly compelling if there is no path to how it can be used or implemented.

Note: It would NOT be based on PSR-0 or PSR-4 or reference the any other way than by example. The examples could very easily just be in the meta document.



Resource Locator Interface

The general idea being closer to what Bernhard built on top of my original lower level resource locator stuff:


In fact, one of the schemes for Bernhard's interface was listed as "classpath://" which was raw access to the autoloader metadata.

The benefits to this is that it *provides* an interface and gives people a way to use it out of the box.

The downsides I see to this is that it has been extremely controversial. There are going to be a lot of people wanting to specify how the interface should be built, what it needs to be able to do out of the box, and how the schemes and namespaces should be handled and defined. I don't really want to wait a year or two to be able to start using this in my projects. :)

I do like this approach, but I also do not want the classpath stuff buried in a full fledged resource locator interface such that the only way someone can actually use the ideas being classpathed resources is by buying into an untested interface entirely.



Classpath => Resource Locator Interface (and optionally a separate classpath scheme)

My preferred approach would be to define and flesh out PSR Classpath Resources in such a way that people can start using it as a concept sooner rather than later. I would expect a few lightweight and simple resource locator implementations and interfaces to crop up.

After that we can then focus on fleshing out a broader PSR Resource Locator like what Bernhard proposed.

We can either add classpath as a scheme and reference the Classpath Resources PSR or we can create a PSR specifically to add the classpath scheme to the resource locator. This would allow the actual resource locator to remain decoupled from the classpath resource PSR and have a lightweight PSR that can easily be superseded to link them together.

The benefits here would be that we can get everything we want but roll it out in pieces.

The downsides to this are that some people seem to have an aversion to having PSRs reference each other. I've never had an issue with this when it makes sense to do so.



All in all, I'm really just excited to get this moving forward. If everyone agrees that we should just focus on a resource locator interface I'm all for it. I'd like to discuss the classpath stuff further, though, to make sure we aren't missing an opportunity there.

Amy Stephen

unread,
Dec 6, 2013, 6:32:19 PM12/6/13
to php...@googlegroups.com
Thanks, Beau, for getting this started.

My Resource package builds on PSR-4 rules - with the exception that I removed the .php class files limit. Otherwise, it uses the same rules to which I added definition of schemes and custom handlers for each scheme. In Molajo, I never directly address a file using it's filesystem address. All files and folders are namespaced and accessed given a scheme and custom handler. In that manner, there is no physical constraint built into the environment.

Relevant Interfaces used in Molajo:
Those are examples of standard resources that FIG could define, given common usages:
  • Class "handlePath" method is registered as an spl_autoloader and it simple includes the file.
  • File "handlePath" method returns the physical path for $this->resource->get('file:///Molajo/Images/Imagename.png').
  • Folder "handlePath" method returns the path to the folder, or a list of folder files, (or recursive folders and files, etc, with or without masking) for a request like $this->resource->get('folder:///Molajo/Model/Resources');
There are also ways for developers to use this approach for custom resource handling. I use resource handlers to locate and handle any Molajo-type extension, ranging from locating and handling a simple Theme to the complexity of the Query Handler which acts as a specialized Factory for a model, pulling together configuration, and constructing the Model and Controller, passing back the Controller instance.  Again, the same type of command $this->resource->get('theme://Molajo/Theme/Foundation') or $this->resource->get('query://Molajo/Model/Articles);

Although I understand the purpose of the classpath approach, it would impose limits to application-wide resources. I am able to locate configuration files that belong to the class using convention -- a shared namespace, a predicatable appended namespace portion for the configuration.

For example, the Molajo\Model\Articles configuration is located in Molajo\Model\Articles\Configuration.xml. So, using the PSR-4 approach, there are tools to build in support for that which classpath offers in Java.

Where classpath falls down is when using a resource locator for application wide resources, like Themes, or Models, or Views, or Images. But, using the PSR-4 approach, schemes, and handlers, I can also address resources across the application.

tl/dr: Molajo Resources uses a combination of namespacing (following PSR-4), schemes (that utilize the namespace data for location), and specialized handlers. I can envision FIG defining standard, shared schemes (for resources like files, folders, classes, etc.) and developers could customize schemes and handlers for their own purposes.

Still happy to work with you on this Beau, if you'll welcome my involvement. =)

Bernhard Schussek

unread,
Dec 6, 2013, 7:25:09 PM12/6/13
to php...@googlegroups.com
Hi Beau,

Thanks for bringing this up again. I was planning to do the same once PSR-4 passed.

I spent a lot of time thinking about this issue since I wrote the blog post and the initial PSR proposal [1]. In fact, by now I'm not even sure anymore whether this topic needs a PSR at all. In my opinion, this could simply be a feature implemented into Composer, which would then register a stream wrapper so that you can do:

file_get_contents('namespace:///Monolog/Logger.php');
file_get_contents('package:///monolog/monolog/README.mdown');

If everyone else agrees that this should be in a PSR though, I'd be willing to act as author or sponsor. However, I'm at a conference this and next week and have only limited time to spend on this topic.

I haven't read Amy's links yet, but I'm planning to do so when the conferences are over.

Cheers,
Bernhard


--


2013/12/6 Beau Simensen <sime...@gmail.com>

--
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/msgid/php-fig/154e297d-de89-42f1-a093-21f11c8bca4c%40googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Donald Gilbert

unread,
Dec 7, 2013, 12:21:49 PM12/7/13
to php...@googlegroups.com
I'm definitely going to be reviewing this further, but I'd like to ask this now, so I can get some clarification of my possible misunderstanding, but why (in everything I've read from people on this) is the stream handler always contain three slashes at the beginning? scheme:///path/to/whaterver 

I know, you're probably going to give the reason of loading a local file in the browser using file:///Users/admin/Sites/whatever, but thats referencing a system path for the local filesystem root. If resources are to be loaded relative to wherever the handler sets the root, I'm fairly certain that something like class://relative/path/to/Class.php makes more sense. Its loading a resource, (like a URI) from the relative path. Putting 3 slashes indicates to me that it's an absolute path from the root.

I would follow the example of http://, ftp://, ssh://.

Minor detail, I know, but it has always bugged me a little. If there are good reasons I shouldn't be bothered by it, please let me know.

Thanks,
Don

Amy Stephen

unread,
Dec 7, 2013, 1:02:19 PM12/7/13
to php...@googlegroups.com
Three leading slashes in the URL only mean the host portion of the address is missing.

For example, ftp://localhost/path would be the same as ftp:///path

Both have three slashes -- one simply has localhost explicitly defined, the other is implicit.

Bernard, thanks for that link. I"ll review that again. Personally, I believe a PSR would be helpful but something very simple along the lines of PSR-4 + schemes. I think your addition of that, as defined in your PSR proposal, was good. I adapted my work to use that and it turned out to be a necessary component to grouping like behavior for file resources. It could be beneficial to standardize a few schemes and describe a common approach to using namespace with any filesystem resource. I think your approach is more inline with my thinking.

The one difference is the classpath. A classpath describes a location, not a behavior or processing requirement for said resource. It's also not necessary since namespaces provide the location. What the scheme should do is provide a way for the application to know -- this resource is handled as thus. In my thinking, namespacing does what classpath does. But scheme, which was introduced by Bernard, provides that hook for the application to separate those resource for specific processing. (Hopefully that makes sense.)


--
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/dwuzIT_jlSA/unsubscribe.
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.

Phil Sturgeon

unread,
Dec 8, 2013, 11:52:24 AM12/8/13
to php...@googlegroups.com
First two // = protocol, the 3rd / is the leading slash of the directory path.

Alexander Makarov

unread,
Dec 11, 2013, 3:24:14 AM12/11/13
to php...@googlegroups.com
Sounds like a good idea to me. We have something similar in Yii https://github.com/yiisoft/yii2/blob/master/framework/yii/BaseYii.php#L111

Bernhard Schussek

unread,
Feb 5, 2014, 9:53:09 AM2/5/14
to php...@googlegroups.com
As a little update, I started working on a library called "Puli" in order to get some practical experience with using the resource locator concept.

The library is available in version 1.0.0-alpha1: https://github.com/webmozart/puli
An experimental integration into Composer is also available: https://github.com/webmozart/composer-puli-plugin

Cheers,
Bernhard

Karsten Dambekalns

unread,
Apr 1, 2014, 5:13:38 AM4/1/14
to php...@googlegroups.com
Hi.

On 07.12.2013, at 01:25, Bernhard Schussek <bsch...@gmail.com> wrote:
> I spent a lot of time thinking about this issue since I wrote the blog post and the initial PSR proposal [1]. In fact, by now I'm not even sure anymore whether this topic needs a PSR at all. In my opinion, this could simply be a feature implemented into Composer, which would then register a stream wrapper so that you can do:
>
> file_get_contents('namespace:///Monolog/Logger.php');
> file_get_contents('package:///monolog/monolog/README.mdown');

In Flow we have resource stream handler that allows to do

file_get_content(‘resource://Acme.Demo/Public/Styles/Foo.css');

The rule is the package key (Vendor.What.Ever.You.Like) is used to identify the package and then we look into that packages “Resources” folder for the path (“Public/Styles/Foo.css” in the example).

The reason we limit that to the “Resources” folder is to make it impossible to fetch source, configuration, … through that - could be a security issue and leads to confusion (user input used to fetch stuff, people starting to use require(‘resource://...'), …).

Regards,
Karsten
signature.asc
Reply all
Reply to author
Forward
0 new messages