PSR 7, PSR 15, PSR 17

455 views
Skip to first unread message

Adam Frederick

unread,
Jul 6, 2021, 11:03:35 AM7/6/21
to PHP Framework Interoperability Group
Please excuse my naivete, but upon making PSR 15 classes, I noticed an issue which I have not found satisfactorily resolved online or in this discussion group.

The idea behind interoperability is to make sure things work on different systems.  Part of doing this is making sure there is a standard interface for normal activity.  Part of normal activity of a middleware would be altering the response body.  But, this presents a problem, since there is no standard method for going about creating a new stream within middleware.

What is the standard for accessing a Psr\Http\Message\StreamInterface implementation from within middleware?
- if I want to modify the body, I have to make a new stream (seeking and writing will often not fit)
I would suggest, given the commonallity of not caring about streams in some middleware, the response gains two functions:
1. "withBodyString()"
2. possibly "getBodyString()" for expectation (just does __toString())

Further, I would suggest two combined things for middleware:
1. ServerRequestInterface should also implement all the PSR 17 interfaces.  Thus, middleware would access a factory like `$handler->createResponse()`.  This itself, the extended interface implementation, could be a PSR.
2. Middleware constructor interface dependencies should be resolved, allowing injection of factories.
Combined, the ServerRequestInterface could just inject itself wherever a PSR 17 factory was required.  However, #2 puts the demand of interface dependency injection the the implementer.

Without a standard, constructing middleware relies on knowing what the framework will do.  If the assumption is that middleware will have the factories injected, this should be stated in the standard as the standard.

Matthew Weier O'Phinney

unread,
Jul 6, 2021, 7:07:39 PM7/6/21
to php...@googlegroups.com
On Tue, Jul 6, 2021 at 10:03 AM Adam Frederick <cap...@gmail.com> wrote:
Please excuse my naivete, but upon making PSR 15 classes, I noticed an issue which I have not found satisfactorily resolved online or in this discussion group.

The idea behind interoperability is to make sure things work on different systems.  Part of doing this is making sure there is a standard interface for normal activity.  Part of normal activity of a middleware would be altering the response body.  But, this presents a problem, since there is no standard method for going about creating a new stream within middleware.

What is the standard for accessing a Psr\Http\Message\StreamInterface implementation from within middleware?
- if I want to modify the body, I have to make a new stream (seeking and writing will often not fit)
I would suggest, given the commonallity of not caring about streams in some middleware, the response gains two functions:
1. "withBodyString()"
2. possibly "getBodyString()" for expectation (just does __toString())

We deliberately chose not to provide methods for altering the message body in either the request or response, and to specifically NOT force the idea that content MUST be a string. There are many cases where strings do not make sense (e.g.,returning images, binary archives, etc.), and limiting the body content to a string made no sense. (On top of this, there are performance considerations when the content gets sufficiently large, and modeling the content as a stream allows PSR-7 implementations to do optimizations that address those issues.) Since it is easy to model string content with the StreamInterface, however, withBody() exists to allow you to inject a custom StreamInterface instance into your request or response.

If you want to force a replacement, compose a PSR-17 StreamInterfaceFactory into your middleware or handler, or instantiate a concrete PSR-7 implementation if you have specific needs you wish to address (e.g., modeling an image or binary archive) 

Further, I would suggest two combined things for middleware:
1. ServerRequestInterface should also implement all the PSR 17 interfaces.  Thus, middleware would access a factory like `$handler->createResponse()`.  This itself, the extended interface implementation, could be a PSR.

We deliberately chose not to have any of the PSR-17 interfaces extend from the others. The reason is that there were too many combinations, and most times, you only need 1, 2, or 3 capabilities, making it relatively easy to compose them into your classes via dependency injection. If you find yourself needing multiple capabilities regularly, create your own interface that extends the set of interfaces you use regularly, and type-hint on that in your middleware or handlers.
 
2. Middleware constructor interface dependencies should be resolved, allowing injection of factories.
Combined, the ServerRequestInterface could just inject itself wherever a PSR 17 factory was required.  However, #2 puts the demand of interface dependency injection the the implementer.

Constructors cannot be specified in interfaces. Well, they can, but PHP does not require implementations to honor them.

The reason is pretty simple: constructors should be specific to a given class.

If we were to add a constructor to a middleware or handler interface, we'd limit what could be injected, meaning that users would not be able to inject other collaborators, such as a database, cache, etc.

And let's not forget: PSR-15 PREDATES PSR-17 anyways.

But the fact that PHP won't do it, and it would preclude having custom constructors, means it's simply not an option.
 

Without a standard, constructing middleware relies on knowing what the framework will do.  If the assumption is that middleware will have the factories injected, this should be stated in the standard as the standard.

There are no assumptions.

You can instantiate a response, URI, stream, etc. directly in your middleware. (and thus tie yourself to a specific implementation)

Or you could inject factories, and use the factories to create the instances.

It's up to you as a developer to define what your class needs to do its work. PSR-7, PSR-15, and PSR-17 are very loosely coupled to allow exactly this.

--
he/him

Adam Frederick

unread,
Jul 6, 2021, 7:47:05 PM7/6/21
to PHP Framework Interoperability Group
specifically NOT force the idea that content MUST be a string
What I presented is not advocating forcing the idea that body must be a string.  In most cases, it is a string of text, and in all cases, it can be a string (although not very useful to have a binary stream turned in to a string - but who would do that).  I would imagine most HTTP middleware in php is dealing with bodies as strings.  You did make a good point on discord, however, that `withBodyString()` would force the response object to know how to create a stream from the string.  I don't think this is so problematic, however, since it already knows about the stream and the stream class,   It would essentially have to do $class = get_class($body_stream);  new $class($string); for the withBodyString function.  And yes, the middleware could also do this, but that is not immediately obvious to middleware makers.

We deliberately chose not to have any of the PSR-17 interfaces extend from the others. The reason is that there were too many combinations, and most times, you only need 1, 2, or 3 capabilities, making it relatively easy to compose them into your classes via dependency injection. If you find yourself needing multiple capabilities regularly, create your own interface that extends the set of interfaces you use regularly, and type-hint on that in your middleware or handlers.

Right, it can be done.  That's not my issue.  My issue is that it is not standardized.  Again, doing it the way you are mentioning relies on the non-standard that whatever is using my middleware resolves the interface dependency.
I agree that it make sense to separate the factories as different interfaces.  But implementations will combine them because the separation is unnecessary (https://github.com/Nyholm/psr7/blob/master/src/Factory/Psr17Factory.php)

 
2. Middleware constructor interface dependencies should be resolved, allowing injection of factories.
Combined, the ServerRequestInterface could just inject itself wherever a PSR 17 factory was required.  However, #2 puts the demand of interface dependency injection the the implementer.

Constructors cannot be specified in interfaces. Well, they can, but PHP does not require implementations to honor them.
Not what I meant by "constructor interface dependencies".  I meant __construct(RequestFactoryInterface $request){}, where you then rely on injection that resolves the implementation of the interface.

But the fact that PHP won't do it, and it would preclude having custom constructors, means it's simply not an option.
 

Without a standard, constructing middleware relies on knowing what the framework will do.  If the assumption is that middleware will have the factories injected, this should be stated in the standard as the standard.

There are no assumptions.

You can instantiate a response, URI, stream, etc. directly in your middleware. (and thus tie yourself to a specific implementation)

Or you could inject factories, and use the factories to create the instances.

It's up to you as a developer to define what your class needs to do its work. PSR-7, PSR-15, and PSR-17 are very loosely coupled to allow exactly this.

Right, so there are two non-standardized options.
1. use dependency injection and rely on the framework injecting the dependencies
2. create my own set of package requirements for my middleware.  The problem with this being the potential for there being 20 PSR 17 implementations, and various middleware all requiring their own.

My thoughts on the matter are about allowing the writer of middleware to have a standardized mechanism for accessing PSR 17 factories.  If dependency injection should be the standard, then standardize it.

But, I think an easier mechanism would be to have an extended RequestHandlerInterface that implements the factories.  "PSR 21 ExtendedRequestHandlerInterface implements ...."

Think about, as a framework, explaining this to middleware developers.
You either end up explaining: 
"in your __constructor, make sure to have the various factory parameters that you need, and then assign them to properties of your object so you can use them in your process method.  We will inject the dependencies as you need them."
Or you tell them
"you can create a stream by doing $handle->createStream()"

What ends up creating more standardized code?




Adam Frederick

unread,
Jul 6, 2021, 7:55:09 PM7/6/21
to PHP Framework Interoperability Group
Revising, `$class = get_class($body_stream);  new $class($string)` would be incorrect (depending in implementation of StreamInterface)

Matthew Weier O'Phinney

unread,
Jul 7, 2021, 1:35:09 PM7/7/21
to php...@googlegroups.com
On Tue, Jul 6, 2021 at 6:47 PM Adam Frederick <cap...@gmail.com> wrote:
specifically NOT force the idea that content MUST be a string
What I presented is not advocating forcing the idea that body must be a string.  In most cases, it is a string of text, and in all cases, it can be a string (although not very useful to have a binary stream turned in to a string - but who would do that).  I would imagine most HTTP middleware in php is dealing with bodies as strings.  You did make a good point on discord, however, that `withBodyString()` would force the response object to know how to create a stream from the string.  I don't think this is so problematic, however, since it already knows about the stream and the stream class,   It would essentially have to do $class = get_class($body_stream);  new $class($string); for the withBodyString function.  And yes, the middleware could also do this, but that is not immediately obvious to middleware makers.

That makes a HUGE assumption, however, that the message instance knows exactly how to construct the stream instance composed into it.

Let me give some examples. In Diactoros, we have several stream types:

- CallbackStream expects a single constructor argument, a callable.
- PhpInputStream expects a single constructor argument, a resource.
- RelativeStream expects two arguments, a StreamInterface to decorate, and an integer offset
- Our primary Stream implementation has two arguments, a resource or string representing the resource to create (e.g., "php://memory"), and a filesystem mode (e.g., 'r', 'a+', 'rw', etc.)

The point is: the message instance cannot know exactly what specific implementation is composed. This is why we provide `withBody(StreamInterface $body)` for replacing the body content.
 
We deliberately chose not to have any of the PSR-17 interfaces extend from the others. The reason is that there were too many combinations, and most times, you only need 1, 2, or 3 capabilities, making it relatively easy to compose them into your classes via dependency injection. If you find yourself needing multiple capabilities regularly, create your own interface that extends the set of interfaces you use regularly, and type-hint on that in your middleware or handlers.

Right, it can be done.  That's not my issue.  My issue is that it is not standardized.  Again, doing it the way you are mentioning relies on the non-standard that whatever is using my middleware resolves the interface dependency.
I agree that it make sense to separate the factories as different interfaces.  But implementations will combine them because the separation is unnecessary (https://github.com/Nyholm/psr7/blob/master/src/Factory/Psr17Factory.php)

Honestly, this is where I'm looking forward to PHP 8.1 and intersection types, as they will make these sorts of things easier. Users can then typehint on `ResponseFactoryInterface&StreamFactoryInterface`, and users can then pick an implementation that provides such combined implementations, or create them on the fly:

    return new class($responseFactory, $streamFactory) implements
            ResponseFactoryInterface,
            StreamFactoryInterface
        {
            public function __construct(
                private ResponseFactoryInterface $responseFactory,
                private StreamFactoryInterface $streamFactory
            ) {}

            public function createResponse(int $code = 200, string $reasonPhrase = '') : ResponseInterface
            {
                return $this->responseFactory->createResponse($code, $reasonPhrase);
            }

            // ... etc
        };

We actually had a number of discussions about this in the PSR-17 WG, and even considered adding some combinations to the http-factory-util package, but there were soooo many variants, and we were concerned people would typehint on the intersection interfaces in the util package instead of the ones defined in the spec, which would hamper interop.

It may be time to revisit that, as I think a few of these have come up as "generally useful":

- ResponseFactoryInterface&StreamFactoryInterface (per the above)
- RequestFactoryInterface&UriFactoryInterface&StreamFactoryInterface
- ServerRequestFactoryInterface&UriFactoryInterface&StreamFactoryInterface&UploadedFileFactoryInterface
- and one combining all of them (e.g., the one from Nyholm/psr7)

That could happen either as an errata/addendum to PSR-17, or a separate spec.

2. Middleware constructor interface dependencies should be resolved, allowing injection of factories.
Combined, the ServerRequestInterface could just inject itself wherever a PSR 17 factory was required.  However, #2 puts the demand of interface dependency injection the the implementer.

Constructors cannot be specified in interfaces. Well, they can, but PHP does not require implementations to honor them.
Not what I meant by "constructor interface dependencies".  I meant __construct(RequestFactoryInterface $request){}, where you then rely on injection that resolves the implementation of the interface.

What are you suggesting, exactly? That we add an example demonstrating this (using constructor injection to provide PSR-17 factories within PSR-15 implementations for purposes of creating PSR-7 instances) to the metadoc for PSR-15? Or documentation detailing how you resolve the interface typehint to an implementation? Or something else?
 
But the fact that PHP won't do it, and it would preclude having custom constructors, means it's simply not an option.
 

Without a standard, constructing middleware relies on knowing what the framework will do.  If the assumption is that middleware will have the factories injected, this should be stated in the standard as the standard.

There are no assumptions.

You can instantiate a response, URI, stream, etc. directly in your middleware. (and thus tie yourself to a specific implementation)

Or you could inject factories, and use the factories to create the instances.

It's up to you as a developer to define what your class needs to do its work. PSR-7, PSR-15, and PSR-17 are very loosely coupled to allow exactly this.

Right, so there are two non-standardized options.
1. use dependency injection and rely on the framework injecting the dependencies

This is exactly what PSR-17 suggests, though! It exists to allow typehinting in your constructors against the PSR-17 factories in your classes so as to prevent directly instantiating a concrete PSR-7 implementation. How the framework does that is really up to the framework. But this was the intent of PSR-17, and it is spelled out clearly in section 2 of its metadoc.
 
2. create my own set of package requirements for my middleware.  The problem with this being the potential for there being 20 PSR 17 implementations, and various middleware all requiring their own.

Your middleware packages should depend on and typehint against PSR-7, PSR-15, and PSR-17, versus specific implementations. If you typehint against those, there are certain guarantees provided for you; most salient to your concerns is the fact that PSR-17's stream factory interface specifically only addresses resource and file-backed streams, which means that you can depend on them to (a) be empty, and (b) be writable. As such, writing your middleware to target the PSR-17 interfaces as constructor dependencies gives you the interop you're looking for.
 
My thoughts on the matter are about allowing the writer of middleware to have a standardized mechanism for accessing PSR 17 factories.  If dependency injection should be the standard, then standardize it.

Again, that is the specific, stated goal of PSR-17, that you inject the factories in your middleware in order to produce PSR-7 artifacts.
 
But, I think an easier mechanism would be to have an extended RequestHandlerInterface that implements the factories.  "PSR 21 ExtendedRequestHandlerInterface implements ...."

This violates the separation of concerns principle, and introduces new questions:

- How does the handler know how to create these artifacts?
- What PSR-7 implementation will the handler use?
- Or is it composing PSR-17 instances to do the work? If so, how does it get access to those? And if it's composing them... why not just call on those factories directly instead of proxying to them?
 
Think about, as a framework, explaining this to middleware developers.
You either end up explaining: 
"in your __constructor, make sure to have the various factory parameters that you need, and then assign them to properties of your object so you can use them in your process method.  We will inject the dependencies as you need them."
Or you tell them
"you can create a stream by doing $handle->createStream()"

What ends up creating more standardized code?

Your second example actually raises more questions for me (see above). (Some call this style "spooky magic from a distance" as it looks convenient, but when you dig, you get a lot of questions about how things actually work, and how you can modify them.)

The first (using DI) is something a framework should cover in its initial tutorials. In some frameworks, reflection-based DI will resolve them for you. In others, you will provide configuration detailing which implementation the DI container should use. Others will have you create and wire in a factory that will handle this detail (and this is where PSR-11 comes into play, as the factory can then retrieve instances from the container to resolve dependencies).

The point, however, is that:

- Your middleware is decoupled from a specific framework or PSR-7/PSR-17 implementation. This allows both composition into different frameworks, as well as substitution for its own dependencies.
- The code is declarative: you know what you need to provide it in order to create an instance. This makes it testable and self-documenting. Your users can find the PSR-7/PSR-17 combination that works for them and directly instantiate the class using concrete implementations.

Am I understanding correctly that you're concerned with the "how do I get my PSR-17 instances to my middleware" question? Particularly so that your middleware can operate with multiple frameworks?

If that's the case, it's an open question. The PSR-11 group worked briefly on a "service providers" spec that would have provided a standard way to configure services for a PSR-11 container, but the problem discovered is that DI containers vary widely in how they do their wiring.

Generally, I find that wiring dependencies into a framework tends to be relatively trivial, which allows me to keep my packages focused on their specific domain, and dependent only on the FIG specs for their HTTP layer. 

Adam Frederick

unread,
Jul 7, 2021, 2:42:54 PM7/7/21
to PHP Framework Interoperability Group
That makes a HUGE assumption, however, that the message instance knows exactly how to construct the stream instance composed into it.

Let me give some examples. In Diactoros, we have several stream types:

- CallbackStream expects a single constructor argument, a callable.
- PhpInputStream expects a single constructor argument, a resource.
- RelativeStream expects two arguments, a StreamInterface to decorate, and an integer offset
- Our primary Stream implementation has two arguments, a resource or string representing the resource to create (e.g., "php://memory"), and a filesystem mode (e.g., 'r', 'a+', 'rw', etc.)

Right, but in general, the concern of withBodyString() can be covered by some default stream that implements the interface.
 
We actually had a number of discussions about this in the PSR-17 WG, and even considered adding some combinations to the http-factory-util package, but there were soooo many variants, and we were concerned people would typehint on the intersection interfaces in the util package instead of the ones defined in the spec, which would hamper interop.

I agree, the countless combinations is not a good idea.  That is why I recommend a full combo only, and I don't see that as being restrictively un-optimized. 
 

It may be time to revisit that, as I think a few of these have come up as "generally useful":

- ResponseFactoryInterface&StreamFactoryInterface (per the above)
- RequestFactoryInterface&UriFactoryInterface&StreamFactoryInterface
- ServerRequestFactoryInterface&UriFactoryInterface&StreamFactoryInterface&UploadedFileFactoryInterface
- and one combining all of them (e.g., the one from Nyholm/psr7)

That could happen either as an errata/addendum to PSR-17, or a separate spec.

Yes, these are individually useful, but I don't see there being an adequate optimization need to make subsets instead of a full set.
 
What are you suggesting, exactly? That we add an example demonstrating this (using constructor injection to provide PSR-17 factories within PSR-15 implementations for purposes of creating PSR-7 instances) to the metadoc for PSR-15? Or documentation detailing how you resolve the interface typehint to an implementation? Or something else?

Initially I was suggesting that you make it part of a standard that implementors of middleware must provide IoC DI to the middleware constructor.  But, this appears to be outside the scope of the standard (it would be dealing with how frameworks deal with middleware construction)
 
This is exactly what PSR-17 suggests, though! It exists to allow typehinting in your constructors against the PSR-17 factories in your classes so as to prevent directly instantiating a concrete PSR-7 implementation. How the framework does that is really up to the framework. But this was the intent of PSR-17, and it is spelled out clearly in section 2 of its metadoc.

Right, and I was suggesting making it a standard that the framework must uphold IoC DI for middleware construction.  This would require both an addendum to defining middleware ( to say factories are injected ), and a PSR that tells frameworks to inject factories.
 
Your middleware packages should depend on and typehint against PSR-7, PSR-15, and PSR-17, versus specific implementations. If you typehint against those, there are certain guarantees provided for you; most salient to your concerns is the fact that PSR-17's stream factory interface specifically only addresses resource and file-backed streams, which means that you can depend on them to (a) be empty, and (b) be writable. As such, writing your middleware to target the PSR-17 interfaces as constructor dependencies gives you the interop you're looking for.

Right, but I was considering what is perhaps a non issue.  I was considering making middleware for a framework which did not do IoC DI.  And, again, my issue is, if IoC DI is the de facto standard, why not make it the actual standard.
 
Again, that is the specific, stated goal of PSR-17, that you inject the factories in your middleware in order to produce PSR-7 artifacts.
 
But, I think an easier mechanism would be to have an extended RequestHandlerInterface that implements the factories.  "PSR 21 ExtendedRequestHandlerInterface implements ...."

This violates the separation of concerns principle, and introduces new questions:

- How does the handler know how to create these artifacts?
There's actually two considerations here.
1. Since both the response and request objects already know how to create new objects of their class by modification of themselves, it is within their realm of concern to create blank objects.  Since these objects are not merely containers (since you can directly modify the content of the headers), it should be expectable that the normal structure of the response can be modified by these objects without additional tools.
2. Since the request handler must return a response, it should know how to return a response - it is within the realm of concern to be able to do this.
- What PSR-7 implementation will the handler use?
This shouldn't matter since it uses an interface.  If the middleware requires a specific implementation, that is different than what the framework is giving, it would require it as a dependency.
- Or is it composing PSR-17 instances to do the work? If so, how does it get access to those? And if it's composing them... why not just call on those factories directly instead of proxying to them?
Access to those would either be through the handler, or through the request and response objects.
Calling the factories directly, either through DI or require/autoload has downsides.

For example, with IoC DI, apart from the issue with making the assumption the framework will provide IoC DI, I could have middleware that has configuration parameters like

class Middleware implements \Psr\Http\Server\MiddlewareInterface{
public function __construct(ResponseFactoryInterface $responseFactory, ServerRequestFactoryInterface $ServerRequestFactory, UriFactoryInterface $uriFactory, $config_param1, $config_param2)
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface {}
}
The problem with this being, prior to presenting this middleware to the framework, you have 3 factory requirements you must resolve prior to adding your own configuration parameters.  (I mentioned how you can still do this with DI IoC with the framework in discord, so it is just an inconvenience)

Your second example actually raises more questions for me (see above). (Some call this style "spooky magic from a distance" as it looks convenient, but when you dig, you get a lot of questions about how things actually work, and how you can modify them.)

I actually think this is the most obvious part.  The framework chooses its own factory default implementations.
 
The first (using DI) is something a framework should cover in its initial tutorials. In some frameworks, reflection-based DI will resolve them for you. In others, you will provide configuration detailing which implementation the DI container should use. Others will have you create and wire in a factory that will handle this detail (and this is where PSR-11 comes into play, as the factory can then retrieve instances from the container to resolve dependencies).

The point, however, is that:

- Your middleware is decoupled from a specific framework or PSR-7/PSR-17 implementation. This allows both composition into different frameworks, as well as substitution for its own dependencies.
Again, it is coupled to frameworks that use IoC DI.  However, I think I will stop pointing this out since, as said elsewhere, it is "de facto standard" and no one seems to want to standardize it to make it de jure
 
- The code is declarative: you know what you need to provide it in order to create an instance. This makes it testable and self-documenting. Your users can find the PSR-7/PSR-17 combination that works for them and directly instantiate the class using concrete implementations.
I can't think of a case needing a specialized testing PSR7 or PSR17 implementation.  If there were such a case, I imagine the frameworks would allow adjusting the default factories used by the request handler
 
Am I understanding correctly that you're concerned with the "how do I get my PSR-17 instances to my middleware" question? Particularly so that your middleware can operate with multiple frameworks?

Not entirely.  I want my middleware to work on _all_ frameworks that meet the standards.  As such, the activities which are within the realm of concerns of the middleware, specifically modifying the response or request, should be standardized, and that standard should mean all frameworks that comply with the standard can run my middleware.  

Perhaps the issue here is the application of separation of concerns. The factories are correctly separate as interfaces for their individual concerns.  But the concern of the request handler is all of the factories, b/c the concern of the request handler is both the request and the response.  Or, taken a different way, the concern of the response object is everything related to changing and viewing the response (all associated factories), and the concern of the request is everything related to changing and viewing the request (all associated factories).

 

Adam Frederick

unread,
Jul 7, 2021, 8:02:39 PM7/7/21
to PHP Framework Interoperability Group
To go further down my path of the last sentence of the last paragraph, you could say that each of these factory outputs are themselves factories.  By returning a new instance of itself when you do something like "withHost()" , Psr\Http\Message\UriInterface is a factory for itself.  And, another way to resolve the non-standardized access to PSR 17 factories is to add the factory methods to each of the factory outputs.  A UriInterface would have a `create` method that had the same input as the factory `createUri()`.  Again, regarding separation of concerns, the creation of itself is in the concern of the object already by it's need to create copies through its other methods.
The only problem I can see with this, from a concern perspective, is perhaps the StreamInterface.  Why would a file stream know how to make a string stream?  However, in implementation, this is rather trivial.  I imagine you have some `class GeneralStream{}`  `class FileStream extends GeneralStream`, and GeneralStream would have `->createFromFile`, `->create`, `->createFromResource` which FileStream would inherit.

Adam Frederick

unread,
Jul 9, 2021, 7:17:08 PM7/9/21
to PHP Framework Interoperability Group
Well, since I don't think this will be solved here, I went ahead and made my own PSRs.  I realize that changing the standard is quite troublesome, and that it's nice to be able to test the waters prior to committing.  So, I present the following

My revision of PSR 7, so that PSR 7 classes come with built in factories

My implementation of PSR 100, using Nyholm/psr7 as a base

My server implementation of PSR 100, using Nyholm/psr7-server as a base

And, my revision of PSR 15, creating something I call AppInterface

Feedback is welcome.

Vincent de Lau

unread,
Jul 10, 2021, 11:09:56 AM7/10/21
to PHP Framework Interoperability Group
Hi Adam,

Here at PHP-FIG we obviously believe that creating standards is a good thing and in principle no topic relevant to the FIG [mission][1] is taboo. Establishing standards is however a group effort and the PHP-FIG bylaws specify a [workflow][2] for creating a new PSR.

To summarize the bylaw, the first official stage is to form a working group of interested people and create a proposal for a new PSR. The proposal should explain the problem and the likely approach. Once that proposal has been accepted a PSR number is assigned. The working group can than work on finalizing the proposal to the point that it can be accepted and published.

If you continue this work outside the FIG procedures, we request that you don't claim any affiliation to the PHP-FIG. Specifically, we ask you to not cause confusion to the PHP community at large by representing your proposal as a PSR.

Kind regards,

Vincent de Lau
PHP-FIG Secretary

[1]: https://www.php-fig.org/bylaws/mission-and-structure/
[2]: https://www.php-fig.org/bylaws/psr-workflow/

Op zaterdag 10 juli 2021 om 01:17:08 UTC+2 schreef cap...@gmail.com:

Adam Frederick

unread,
Jul 10, 2021, 12:16:39 PM7/10/21
to php...@googlegroups.com
Hi Vincent,

Here at PHP-FIG we obviously believe that creating standards is a good thing and in principle no topic relevant to the FIG [mission][1] is taboo.

I agree 
 
Establishing standards is however a group effort and the PHP-FIG bylaws specify a [workflow][2] for creating a new PSR.

This depends.  It does not take a group to create a standard.  Most standards arise from good inventions that set the standard by doing well.  The adoption and sometimes the perfection of a standard, however, requires a group.
 

To summarize the bylaw, the first official stage is to form a working group of interested people and create a proposal for a new PSR. The proposal should explain the problem and the likely approach. Once that proposal has been accepted a PSR number is assigned. The working group can than work on finalizing the proposal to the point that it can be accepted and published.

That is fine in writing, but when I approached FIG through discord, it took me repeating my issue in various ways over two days for Matthew to finally realize the nuance of what I was saying.  And in that two days, perhaps prior to realizing the nuance, Matthew presented a rather patronizing post to me that both you and Crell thumbed up.  You also somehow spent those entire two days thinking I didn't know how to do DI, and Crell spent those two days thinking my issue is that I had empathy for developers who didn't know how to do DI
""" Quote from Crell
HHR [me]: But what about developers who don't know how to use DI properly?
FIG: Um.  What about them?  That's their problem.
"""
Like I said in discord, I was disheartened by this interaction.  However, Matthew has seemingly understood my issue and provided useful insights.
 
If you continue this work outside the FIG procedures, we request that you don't claim any affiliation to the PHP-FIG. Specifically, we ask you to not cause confusion to the PHP community at large by representing your proposal as a PSR.

I do not claim any affiliation with FIG.  If so desired, I'll even put such in the READMEs and anywhere else you want.  The phrase PHP standard recommendation is generic and the most suiting phrase for the description of what I am presenting.  If you have another name for a PHP standards recommendation I could use, I'll consider it.  But I already made the PSRs start at 100 for the explicit purpose of separating them from FIG PSRs.  As I presented in the PSR 100 README:

"I've numbered this PSR 1XX under the premise FIG will not get to 1XX in a long time, or will never get to it, and so, my PSR's will not conflict for a very long time, and if they ever conflict, and my standards are not accepted, they can just be ignored at that time."

If someone at FIG, who would not be met with the same adversity, wants to collaborate in making a FIG PSR, that would be fine with me.

Finally, in lacking a better name, I will be coming out with a PSR 102 that I hope will fully standardize frameworks at the app level (it is an improvement on and extension of my PSR 101)


- Adam F


--
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/CtluNYS3QxY/unsubscribe.
To unsubscribe from this group and all its topics, send an email to php-fig+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/php-fig/25a23980-fceb-4470-bbe0-82cf1228c434n%40googlegroups.com.

Larry Garfield

unread,
Jul 10, 2021, 12:44:57 PM7/10/21
to PHP-FIG
On Sat, Jul 10, 2021, at 11:16 AM, Adam Frederick wrote:


> > If you continue this work outside the FIG procedures, we request that you don't claim any affiliation to the PHP-FIG. Specifically, we ask you to not cause confusion to the PHP community at large by representing your proposal as a PSR.
>
> I do not claim any affiliation with FIG. If so desired, I'll even put
> such in the READMEs and anywhere else you want. The phrase PHP
> standard recommendation is generic and the most suiting phrase for the
> description of what I am presenting. If you have another name for a
> PHP standards recommendation I could use, I'll consider it. But I
> already made the PSRs start at 100 for the explicit purpose of
> separating them from FIG PSRs. As I presented in the PSR 100 README:

"The phrase PHP standard recommendation is generic"

Incorrect. "PSR" is a very well-understood term for the specifications published by FIG, specifically. If everyone went around calling every package they released "PSR", it would only do harm to the community because it would confuse everything.

Doctrine for instance is super popular, more popular than some FIG specs, but if they started calling Doctrine ORM "PSR-30"... that would just be a lie.

> "I've numbered this PSR 1XX under the premise FIG will not get to 1XX
> in a long time, or will never get to it, and so, my PSR's will not
> conflict for a very long time, and if they ever conflict, and my
> standards are not accepted, they can just be ignored at that time."

And when 30 other people decide to start publishing "PSRs" and randomly grabbing various number ranges? There are people who didn't think FIG would get to 10 specs, much less 20 PSR numbers, including some of its founders.

If you want to publish a package that combines PSR-15 and PSR-17 in some way, you're certainly welcome to do so. But by using the term "PSR" you are implying an affiliation with FIG and its approval process that is not present, and thus misrepresenting your work. There is no situation in which that is not harmful and unprofessional. Most framework leaders would recognize it as such and actively avoid your "standards" for that reason.

--Larry Garfield

Adam Frederick

unread,
Jul 10, 2021, 12:54:24 PM7/10/21
to php...@googlegroups.com
Larry, if two others here would second and third your opinion, I will explain why you are wrong.

--
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/CtluNYS3QxY/unsubscribe.
To unsubscribe from this group and all its topics, send an email to php-fig+u...@googlegroups.com.

Michelle Sanver

unread,
Jul 10, 2021, 3:19:57 PM7/10/21
to php...@googlegroups.com
Hi Adam and Larry,

I have read through some of this long  discussion, and in essence, I agree with Larry thay using “PSR” in the PHP community for a standard that is not a FIG standard is harmful to the community and devalues the work of FIG. 

We have been around for a long time; when PHP developers see “PSR” they will look it up at FIG, not find it; and get confused. Let’s not confuse our wonderful community. 

I’m sorry Adam that you felt that the communication was patronizing. That is perhaps something that we can look into. 

Sincerely,
Michelle Sanver 
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 view this discussion on the web visit https://groups.google.com/d/msgid/php-fig/CAPSiWTo%3DUYjj_gpky3gv0NfH%2B%2BhsR-R7WxCTqdFpB1atLg4OQg%40mail.gmail.com.

Adam Frederick

unread,
Jul 10, 2021, 4:07:58 PM7/10/21
to PHP Framework Interoperability Group
Will anyone else second Larry?

Hi Michelle, 

Because this is a first, I will address your points.

I have read through some of this long  discussion, and in essence, I agree with Larry thay using “PSR” in the PHP community for a standard that is not a FIG standard is harmful to the community and devalues the work of FIG. 

My PSRs literally rely on FIG PSRs and refer to them in the documentation.  How are my prototypes going to hurt the community when almost none of the PHP community knows about them?  When they are designed not to conflict?  How do my PSRs, that pay reverence to the existing PSRs by extending them, devalue FIG PSRs?
 
We have been around for a long time; when PHP developers see “PSR” they will look it up at FIG, not find it; and get confused. Let’s not confuse our wonderful community. 

The idea that google will choose to show my PSRs over FIG's PSRs is kind of absurd.  And, the case you present is also kind of absurd since I refer directly to the FIG PSRs in the documentation, and anyone arriving at my PSRs would be directed to FIG PSRs if that is what they were looking for.  And like I already said, I'm perfectly willing to add a header "Not a FIG PSR" if desired.
 
I’m sorry Adam that you felt that the communication was patronizing. That is perhaps something that we can look into. 

Don't worry about it - it is truly something you can not fix.
 

Buster Neece

unread,
Jul 11, 2021, 1:37:07 AM7/11/21
to PHP Framework Interoperability Group
Adam,

I know I don't chime in much here on the message boards, but I wanted to drop in and say hello, not necessarily in an official capacity but just as a developer in the community who's been a long-time follower of the FIG and the PSR standards.

I very much understand the feeling of being up against a monolithic entity where it seems hard to get a word in edgewise or get your foot in the door. A lot of us feel this way when contributing to projects larger than our own, and for me personally, the fear of getting a negative response is what has kept me from submitting many contributions upstream to the projects my own software depends on. That feeling is real and valid, and it's imperative for the larger institutions to do what they can to remain approachable despite their size and momentum.

In that context, there's nothing at all wrong with submitting ideas to the group here. Your ideas aren't without precedent, either, since I've seen numerous implementers of the PSR standards lump them together into singular libraries that cover multiple standards at once or extend the standards to be easier to use in their own context. By all accounts, even if your repositories didn't wind up as FIG standards themselves, they could continue to exist as standalone code and would likely be useful to a number of people looking to implement the combined standards in a friendly way.

I also agree with Michelle in that it is unfortunate you were met with a response that you felt patronized your contributions. It's important that any interactions with participants in the FIG process be respectful and professional. By that same token, however, I'm not sure that messages like:

> Larry, if two others here would second and third your opinion, I will explain why you are wrong.

...convey that level of respectfulness or professionalism either.

I think the friction you're feeling with the FIG group doesn't stem from the content of your suggestions themselves, but rather the manner in which you presented them, which was in the form of a GitHub organization named "PHP-SG" with standards that presented as numbered "PSR"s.

What does "PHP-SG" stand for? Absent any clarifying information on my side, and given the organization's only contents are these new "PSR" standards, I'd have to assume it stands for something like "PHP Standards Group".

So, you've submitted your ideas here through an organization that may or may not imply its own status as a standards group, using the same terminology the FIG uses for its own recommendations, which have been refined and polished through group collaboration into their final forms.

Surely you see the reason for any pushback you're feeling here.

I know your response thus far has been that the phrase "PSR" is a generic one and that your own "PSRs" aren't popular enough from an SEO perspective to compete with the official ones. To the second point, I think most of the folks here would argue that it isn't your project's relative popularity that is the problem, but rather the precedent that is set when anyone who proposes an idea to the PHP-FIG spins up their own organization, creates repositories and assigns their own FIG numbers to their own code. This would be an immensely confusing mess in very short order, and would leave a hundred repositories scattered across GitHub at varying stages of completion or stability that are all named "PSR-something". Even if developers weren't likely to find those repositories first, the idea that they would find them at all, and then associate them with the same process that the existing PSRs they're familiar with have gone through, is cause for concern.

To your point that the phrase "PSR" is generic, I would be inclined to agree if there was any prior art whatsoever that suggested that was the case. If you ask people from all around the PHP community what a PSR is, I would wager that all of the ones who know the term would direct you to one of the PHP-FIG standards. The PHP core team uses a different name for their own proposals, and none of the popular frameworks out there (even the ones who don't necessarily adhere to the PSR standards) have made their own standards and called them "PSRs". This is basically a first, so that's why you're seeing such a strong pushback on the concept, because nobody involved wants to set the precedent that you can make your own PSRs when submitting ideas to the FIG, or in general.

So, really the long and short of it here is it's all in the naming. If you can understand where the FIG is coming from in that regard, then we may be able to move forward in a productive way.

 - Buster Neece

Ian Littman

unread,
Jul 11, 2021, 2:24:09 AM7/11/21
to php...@googlegroups.com
Adam,

Showing up to this thread late and likewise in a capacity no more official than yours. I'll add my opinion in with Larry's to get closer to the requisite threshold where you tell FIG, which has gotten buy-in from various maintainers to use the same interfaces, just how wrong they are. While grabbing a namespace on GitHub purporting to be, well, more than yourself.

There is a difference between APIs I like and hard-fought specs with organizational buy-in, multiple distinct implementations...and a PSR number. Note that even FIG doesn't slap a number on *its own* specs until they've made it far down the process. They're named drafts for the first bit. Hopefully you can understand the consternation arising when you decide to skip that step after framework/middleware maintainers reply "yes, we thought of that, and here's why we didn't go down that route."

At the end of the day, specs are only as good as their adoption, and FIG cannot, say, mandate Laravel, Symfony, or even Laminas to implement anything FIG turns into a numbered PSR. Nor does it take FIG's blessing for multiple frameworks to implement a given pattern that they see as useful. So if your concern is getting two frameworks that you like to adopt your set of interfaces, the most expedient way to proceed would be to see if those frameworks will accept a PR integrating the interface. Bonus points if the implementations are different, matching the framework's internals.

Heck, if the idea is solid enough, maybe after the first framework merge you'll get someone willing to implement within their framework for you, which would provide you enormous validation. Or maybe they discuss with you and the result is a better spec, at which point you go back to the first framework you implemented with and change things before the de facto standard gets too set in stone.

In the mean time, assuming you're operating in good faith in the direction of FIG, throwing numbered "PSRs" around is improper signaling, as a few folks have mentioned.

With that in mind, which two frameworks do you intend to individually convince to accept a PR exhibiting the functionality you're championing?


Adam Frederick

unread,
Jul 11, 2021, 9:12:11 AM7/11/21
to PHP Framework Interoperability Group
On Saturday, July 10, 2021 at 10:37:07 PM UTC-7 Buster Neece wrote:
Adam,

I know I don't chime in much here on the message boards, but I wanted to drop in and say hello, not necessarily in an official capacity but just as a developer in the community who's been a long-time follower of the FIG and the PSR standards.

I very much understand the feeling of being up against a monolithic entity where it seems hard to get a word in edgewise or get your foot in the door. A lot of us feel this way when contributing to projects larger than our own, and for me personally, the fear of getting a negative response is what has kept me from submitting many contributions upstream to the projects my own software depends on. That feeling is real and valid, and it's imperative for the larger institutions to do what they can to remain approachable despite their size and momentum.

In that context, there's nothing at all wrong with submitting ideas to the group here. Your ideas aren't without precedent, either, since I've seen numerous implementers of the PSR standards lump them together into singular libraries that cover multiple standards at once or extend the standards to be easier to use in their own context. By all accounts, even if your repositories didn't wind up as FIG standards themselves, they could continue to exist as standalone code and would likely be useful to a number of people looking to implement the combined standards in a friendly way.

I also agree with Michelle in that it is unfortunate you were met with a response that you felt patronized your contributions. It's important that any interactions with participants in the FIG process be respectful and professional.

As I mentioned on discord
"Any way, thanks for trying to be helpful. I'm sure you guys get a lot of "what about x" when the answer should be obvious, and that has partially directed this conversation."

In the position of representing FIG, one will probably get a lot of obvious questions.  After years of dealing with mostly the same questions, one becomes paradigmed into funneling all questions into one of the obvious questions without attending to the details of the question

 
By that same token, however, I'm not sure that messages like:

> Larry, if two others here would second and third your opinion, I will explain why you are wrong.


There's really no great way to handle that situation.

Larry wrote a very long email.  It would take me a long time to explain the problems with it, and I've been busy building the prototype implementation of my PSR 102. I've interacted with Larry on discord, and I've found he often misinterprets me and misapplies concepts in an effort to correct me, and that interacting with him can be tiresome.  For instance, he tried to compare the mistake {of adding a log setter method on PSR 3 rather than using dependency injection} to my suggestion of having the Handler also be a factory.  Here was that interaction:


realize there are issues

Larry: "Use dependency injection" is enough of a de facto standard already that there's little reason to specify it. And the alternative, setter injection, is widely recognized as inferior. Only one spec included that, PSR-3, and LoggerAwareInterface is, I would argue, recognized in hindsight as a mistake.
Me: "I haven't used PSR 3, I'll have to take a look
[6:19 AM]
but, to mention what I was going to say
[6:19 AM]
1. potentially middleware will want access to factories before the "process" method is called
[6:20 AM]
2. having an extension PSR would potentially create a mismatch of expectation in middleware(edited)
[6:21 AM]
right, slightly different situation with the logger though
[6:22 AM]
with the middleware, you already have handler being injected
[6:22 AM]
the question is about what that handler can do
[6:22 AM]
it's not exactly the case of $middleware->setFactory()
[6:23 AM]
since the middleware already expects the handler
[6:23 AM]
@Crell
[6:24 AM]
even further, there is an oddity of set handler for logger
[6:24 AM]
whereas, a framework uniformly handles IoC dependency injection
[6:25 AM]
it would have to have a special case for handling something implementing LoggerAwareInterface
[6:25 AM]
it would have to check if the class implemented it, and then it would have to call the setter


This is an example of misapplication of concepts in an attempt to correct me.  But, as I already mentioned, Larry also spent two days thinking my issue was empathy for those who didn't know how to use DI.

I could have ignored Larry, which is often what the "professional" thing to do is.  Or I could have been more ambiguous about my requirement to respond and said "Does anyone else feel this way"?  But, even that second option is bad, b/c I don't want people who feel and don't think to second Larry and make me spend time responding.

 
...convey that level of respectfulness or professionalism either.

Yes, it was intentionally curt with a purpose.  I could go on a tangent about how being overly nice can make bad programming communities, but I wont.  
 
I think the friction you're feeling with the FIG group doesn't stem from the content of your suggestions themselves, but rather the manner in which you presented them, which was in the form of a GitHub organization named "PHP-SG" with standards that presented as numbered "PSR"s.

No.  The friction was occurring in discord way prior to my decision to even make those PSRs.  I would posit the friction stems from what I talked about with getting stuck in paradigms owing to answering the same questions over and over.
 
What does "PHP-SG" stand for? Absent any clarifying information on my side, and given the organization's only contents are these new "PSR" standards, I'd have to assume it stands for something like "PHP Standards Group".

I didn't want to promote myself in putting out PSRs, so my option was to make a PHP Standards Group.  I imagined it might be useful to have a group that is not centered on interoperability, and that can put out prototype standards that don't need to spend as much time going through the FIG process.

Surely you see the reason for any pushback you're feeling here.

Yes, I always see the reason.
 

I know your response thus far has been that the phrase "PSR" is a generic one and that your own "PSRs" aren't popular enough from an SEO perspective to compete with the official ones. To the second point, I think most of the folks here would argue that it isn't your project's relative popularity that is the problem, but rather the precedent that is set when anyone who proposes an idea to the PHP-FIG spins up their own organization, creates repositories and assigns their own FIG numbers to their own code. This would be an immensely confusing mess in very short order, and would leave a hundred repositories scattered across GitHub at varying stages of completion or stability that are all named "PSR-something".

In judging possibilities, you have to deeply consider probabilities or you will find yourself carried away with absurdities.  Nothing has stopped the scenario you are describing from having happened already, over the passed many years.  Someone could publish as PSR without even having contacted FIG.  But, why does this not occur?
1. Most PHP developers are not interested in making standards.  
2. Some subset of PHP developers are interested in following standards, but they want those standards to be from an established organization, so they will only follow standards from FIG
3. Consequent to #1 and #2, there is almost no reason to make and no body that will make PSRs apart from FIG
4. The people who are competent to make standards are normally busy, and often already part of framework teams
5. Consequent to #5, being part of a framework team, those who would make a standard and are competent to do so would want to go through FIG so as not to appear biased towards their framework

I could probably go on, but time is precious.
 
Even if developers weren't likely to find those repositories first, the idea that they would find them at all, and then associate them with the same process that the existing PSRs they're familiar with have gone through, is cause for concern.

Just to curtail this conversation, I will go ahead and put the header on all the PSRs of
"This is not a FIG PSR.  This PSR does not comply with the rigor applied to FIG PSRs"
 
To your point that the phrase "PSR" is generic, I would be inclined to agree if there was any prior art whatsoever that suggested that was the case.

You see, this is part of where Larry was wrong.  I did not say the "PSR" was generic, I said PHP Standard Recommendation was generic.  The consequence of that, however, is that the long phrase needs to be abbreviated into PSR to be manageable.
 
If you ask people from all around the PHP community what a PSR is, I would wager that all of the ones who know the term would direct you to one of the PHP-FIG standards.

Again, I did not argue against this.
 
The PHP core team uses a different name for their own proposals, and none of the popular frameworks out there (even the ones who don't necessarily adhere to the PSR standards) have made their own standards and called them "PSRs". This is basically a first, so that's why you're seeing such a strong pushback on the concept, because nobody involved wants to set the precedent that you can make your own PSRs when submitting ideas to the FIG, or in general.

Perhaps if I had not spent so much time on this issue responding to emails that are not technical feedback about the content of the PSRs, and someone had proposed I instead name them "PPSR" for proposed PSR or prototype PSR, I might be inclined to spend time renaming them.  But at present, I want to finish PSR 102 and get back to productive things.
 
So, really the long and short of it here is it's all in the naming. If you can understand where the FIG is coming from in that regard, then we may be able to move forward in a productive way.

I do understand.   I expect the probability that 
{
       my non-audienced PSRs will spawn an uncontrollable tidal wave of php developers who suddenly want to make their own PSRs, and that this tidal wave buries FIG in search engines and makes everyone totally confused about there being FIG PSRs, and instead think that PSR stands for programming standards recommendation, which leads to another tidal wave of developers in all languages making their own PSRs and flooding github to the point where microsoft begins charging for personal accounts
is about 0.

Adam Frederick

unread,
Jul 11, 2021, 11:54:31 AM7/11/21
to PHP Framework Interoperability Group
 I'll add my opinion in with Larry's to get closer to the requisite threshold where you tell FIG, which has gotten buy-in from various maintainers to use the same interfaces, just how wrong they are. While grabbing a namespace on GitHub purporting to be, well, more than yourself.

Not only is your use of sarcasm unprofessional, but you have lied: I did not purpose to tell FIG how wrong they were - only Larry and those who second him.
  
Hopefully you can understand the consternation arising when you decide to skip that step after framework/middleware maintainers reply "yes, we thought of that, and here's why we didn't go down that route."

I'm seeing a pattern here.  This is quite ignorant on your part.  I will explain for others, though.

""yes, we thought of that, and here's why we didn't go down that route."""

This did not happen.  Go read the last email by Matthew and then my response to that.  what happened was, in summary:

Matthew: Oh, I finally think I understand what your issues are.  Those are difficult issues, there are many things to consider about them, and it remains mostly unresolved.  I'm hoping PHP 8.1 will allow us to resolve it better.  [Ending with] "If that's the case, it's an open question"
Me: Yes, the points you bring up are interesting.  As counterpoints, you can do it X way, and you can also conceptualize it X way.
Matthew: silence
Me: well, I guess since no one is responding for a while to my valid counterpoints, I'll just have to make my own PSRs to solve the issue I brought up


Perhaps people in the list don't understand where all this spawned from.  So, I will quote myself from discord:

right, but that means either 1. having a dependency within your middleware, or writing a PSR 7 implementation within your middleware
[8:03 AM]
both of which are problematic
[8:03 AM]
my perspective, from someone who just wants to write middleware that replaces "bill" with "bob"
[8:03 AM]
is that my middleware should have no package dependencies
[8:04 AM]
that I don't want to rely in injection
[8:04 AM]
and that I don't want to write my own psr 7 implementation just to change the body
 
With that in mind, which two frameworks do you intend to individually convince to accept a PR exhibiting the functionality you're championing?

My mind is presently only on the perfection of the concept, not which frameworks may use it.  The implementation of PSR 102 itself is fairly complex.  But, in cursory inspection, I expect Laravel and Symfony could both implement it, since it (sort of) allows for the Symfony kernel event model, but using a different paradigm.

I'll share something you posted to me on discord to give a better understanding to those reading the mailing list.

""" iansltx — Yesterday at 11:52 PM
Though, looking at the blog that shares an IP, and inexplicably a TLS cert, with your dot-org, I'm not sure you're operating in good faith here, given the ink poured a out how PSR-12 (and, I suppose, 1 and 2) have no place in FIG.
"""

What exactly are my bad faith motives?  Like I said in discord, at the start, my desire was to replace "bill" with "bob", (because bills have no place in programming).  My "blog" on CLRMO.com stems from me looking into the PSRs after ignoring them until just a little while ago.  
That you should dismiss me because I don't agree with PSR 12 really says something about you.  I find that those who cling to standards like zealots and act as gate keepers reduce useful progress and lead to stagnant, inefficient status quos that serve their own unwillingness or incapableness to change.

But, let's visit the very sane opinions I have about PSR 12 (note, I didn't make a PSR XXX to replace PSR 12 b/c I think it is fine for most people)

1. The standard of spaces makes sense for most big projects, but does not make sense as a standard for all projects.  There is nuance to the tabs vs spaces debate which, as far as I have seen, in over 15 years of programming, has only been explained my me, here: https://clrmo.com/2021/07/spaces-vs-tabs/
2. The standard of camelCasing is good particularly in frameworks and common tools, but it is a bad standard for apps.  I explain this situation
3. The placement of "{" on a new line for methods reduces the amount of useful code on the screen I can see at once.  Even google presents this as an objective:
"
  • The basic principle is: The more code that fits on one screen, the easier it is to follow and understand the control flow of the program. Use white space purposefully to provide separation in that flow.
"
4. Code styling doesn't matter that much.  From the "blog"
"
  • Different styles don’t matter so long as they are clear. The mixing of styles is mostly a problem when tabs and spaces are mixed, which can be prevented by a good editor. Programmers have been modifying each others code for decades and different, clear, styles have not prevented interoperability
"

5. "
  • PSR 12 should not be a FIG PSR. The point of interoperability is whether some code will work in different environments. PSR 12 is for how programmers react to code, not for how the code functions in different environments.
"

All of these are valid points, but none of them led me to make a PSR to replace PSR 12, and I have no intention of doing so.


Ian, I really do suspect that you are the sort of person that would cut me off at the knees to prevent my valid criticism. 

Ian Littman

unread,
Jul 11, 2021, 12:06:15 PM7/11/21
to php...@googlegroups.com
Adam,

You're posting to the FIG list, so you telling Larry, Buster, myself and others why we are mistaken has the side effect of also telling FIG.

Given that you believe that Laravel and Symfony could make use of your spec, it's worth approaching those maintainers directly, as neither are members of FIG.

If you're clear about your goal here (e.g. framework adoption within X timeframe), there may be better ways of achieving that goal than posting to the list.

Ian

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

Adam Frederick

unread,
Jul 11, 2021, 8:01:10 PM7/11/21
to PHP Framework Interoperability Group
I've updated my PSRs with notices about FIG PSRs

I've released PSR 102

And the Implementation

From the beginning, I wanted to solve the "bill" to "bob" issue.  Then, I wanted technical feedback on my PSR 100 and 101.  Presently, I would very much appreciate technical feedback on my PSR 102 and the implementation.  

Alessandro Lai

unread,
Jul 12, 2021, 12:24:03 PM7/12/21
to PHP Framework Interoperability Group
First, I'll try to weigh in as in official capacity, because I lagged a bit in keeping up with this discussion, so excuse me for being late:

Adam, I'm sorry that you have encountered friction in trying to propose your ideas in this venue, but I have to ask you to check how you're expressing yourself lately.
Surely, you probably feel not completely welcome here, and multiple people here (like Michelle, which is a CC member) recognized that we should do better, and I ask we all do. But I have to call you out here, before this discussion goes down further the wrong way.

As for why I'm intervening here: in you latest answers, you've stepped over a line that I, as a moderator here, cannot ignore. Namely:

 - you answered to Larry patronizing him (supposedly in retaliation), without dignifying him of a proper response (the "Larry, if two others here would second and third your opinion, I will explain why you are wrong." answer)
 - you claimed multiple times that you were busy building stuff, hence valuing your time, but you dismissed others when they weren't able to respond to you in a timely fashion, hence not valuing theirs
 - you rudely accused PHP-FIG members of lying and being ignorant just because they were disagreeing with you
 - you ignored and dismissed multiple accounts from multiple people discouraging you to use the "Standards Group" and "PSR" names
 - you dismissed the possible implications of such course of action, which I consider not taking any responsibility for your actions

On this last two points, I would like to remind you that "PHP Standards Group" was the original name of the PHP-FIG, and the founders abandoned it just because of the sheer amount of backslash from the PHP community at large; so that TWO different reasons to not use this name; so I, again, encourage you to not use those names, to avoid confusing users, but instead to have a name to call your own, if you really want to push your ideas outside of the PHP-FIG. I hope you can reconsider that in a show of good faith, so that we can go on and start discussing on technical merits only from this point further.

Adam Frederick

unread,
Jul 12, 2021, 12:31:48 PM7/12/21
to PHP Framework Interoperability Group
I will say, Ian, you are the only one here from FIG who has been intentionally disrespectful.  Your second posting has confirmed suspicions of mine.  Not only have you impugned my character on discord and lied about the summary of events in this thread, but you are now attempting to misdirect even further.  So, I will dissect.
 
You're posting to the FIG list, so you telling Larry, Buster, myself and others why we are mistaken has the side effect of also telling FIG.

This is complete misdirection.  Let's see what you are attempting  to misdirect: a quote of yours from the first posting:
"""
where you tell FIG, which has gotten buy-in from various maintainers to use the same interfaces, just how wrong they are.
"""
Again, I did not tell FIG, I told Larry I would explain how his opinions in a specific message were wrong.  But, now, you are trying to misdirect people again: that some how, by individually interacting with people on this list after I made that statement, and that because that series of interactions has included Larry, You, and Buster, that the meaning of my passed statement about Larry's email should actually be interpreted as  "telling FIG ... how wrong they are".

What I have seen is that everyone who seconded Larry's posting actually each had their own caveats that I had to separately address.

Btw, @Buster, sorry for the informal response,  I was responding to what I saw as a hen pecking by multiple people while under time constraints, and as far as I knew at the time, you were just some programmer who happened to be on the mailing list.


Ian, I suspect that your rapid response to my rather lengthy response to you served as an attempt to cover my response to yours where I point out many traits that characterize you as a bad actor.




The rest of your email, while no longer misdirecting, is diverting, but I will address it anyway since other may be interested.
  
Given that you believe that Laravel and Symfony could make use of your spec, it's worth approaching those maintainers directly, as neither are members of FIG. 

If you're clear about your goal here (e.g. framework adoption within X timeframe), there may be better ways of achieving that goal than posting to the list.

@all
I have been clear at the outset.  I want a standardized (not de facto standard) way of changing the response body in middleware.  When Matthew stepped out, and in view of the silence of FIG, in order to achieve this, I had to make my own.
Under the consideration presented by Matthew that the request handler might not be appropriately a factory (this is an opinion I don't hold), I reconsidered, and realized that the whole App level could be standardized, and this would seemingly be the ultimate goal of FIG.  Because of this realization, I continue to post on here about PSR 102, which can be extended with PSR 11 and PSR 14 to create a fully functional app that does layering (middleware, outerware), events, and acts as a service container.
I think this level of standardization would be extremely beneficial for PHP.  I also think that my LayeredApp PSR 102 very fully addresses the needs of frameworks.


I was expecting some technical feedback.  Even if it was the cursory feedback that I built in to my PSR 100 implementation README, that the problem I present is actually a problem of Liskov substitution principle violation.

Adam Frederick

unread,
Jul 12, 2021, 12:38:12 PM7/12/21
to PHP Framework Interoperability Group

 - you answered to Larry patronizing him (supposedly in retaliation), without dignifying him of a proper response (the "Larry, if two others here would second and third your opinion, I will explain why you are wrong." answer)
This was not 

 This was not retaliation.  As I mentioned, I have not done well at explaining things to Larry, so I wanted to make sure other people benefited by my effort which would otherwise likely have been wasted.

 - you claimed multiple times that you were busy building stuff, hence valuing your time, but you dismissed others when they weren't able to respond to you in a timely fashion, hence not valuing theirs
What?  Who did I dismiss?  I dismissed no one.  I only saw that Matthew had become silent and presented that the issue I presented was unsolved, so I decided to solve it.
 
 - you rudely accused PHP-FIG members of lying and being ignorant just because they were disagreeing with you
As far as I know, I only accused Ian of lying.  Being ignorant is another matter that is fully acceptibly caused by lack of time.
 
 - you ignored and dismissed multiple accounts from multiple people discouraging you to use the "Standards Group" and "PSR" names
Wow.  This itself is a misrepresentation.  I have responded to each of the points by everyone about my use of PSR except for Larry, with reason.
 
 - you dismissed the possible implications of such course of action, which I consider not taking any responsibility for your actions
I analyzed implications - to which no one has contended my analysis.
 

On this last two points, I would like to remind you that "PHP Standards Group" was the original name of the PHP-FIG, and the founders abandoned it just because of the sheer amount of backslash from the PHP community at large; so that TWO different reasons to not use this name;
I didn't know that until afterwards.
 
so I, again, encourage you to not use those names, to avoid confusing users, but instead to have a name to call your own, if you really want to push your ideas outside of the PHP-FIG. I hope you can reconsider that in a show of good faith, so that we can go on and start discussing on technical merits only from this point further.

I encourage you to really read my responses and present me with counter arguments rather than telling you read through the thread in a cursory manner and decided I'm a bad actor.

Alessandro Lai

unread,
Jul 12, 2021, 4:17:41 PM7/12/21
to PHP Framework Interoperability Group
I'm sorry that you decided to go forward with this non-productive attitude. I will give you my last detailed answer and then I'll be forced to lock down this thread. This discussion is going nowhere, since you demonstrate no willingness in hearing everyone objections, you don't want to form a group to discuss your proposal and you don't want to follow PHP-FIG process to push forward your ideas.

This is open source, noone is paid to stay here and/or give you a response; you where met with explanations and a request to follow the proper, published workflow for PSRs, and instead you decided to go on all alone, creating repos and demanding us for technical review of your solo job.
There's a reason for which we require working groups to be formed around PSRs: those are complicate matters, because generalizing and standardizing even the smallest bit of code is a hard problem. You need multiple point of views to discuss and pour over a simple interface before being able to say "this is worth as a PSR and will promote interop". Look at PSR-11, it's a single interface with two bare-bone methods, it required months of discussions and previous work (see container-interop) but it was hugely successful.

> This was not retaliation.  As I mentioned, I have not done well at explaining things to Larry, so I wanted to make sure other people benefited by my effort which would otherwise likely have been wasted.

So you were not retaliating, you are considering speaking to Larry "wasted time". Again, this is not respectful behavior, especially toward a CC member which is in the nominal position of giving you advice and opinions on what you put in front of the PHP-FIG.

> What?  Who did I dismiss?  I dismissed no one.  I only saw that Matthew had become silent and presented that the issue I presented was unsolved, so I decided to solve it.

Matthew didn't step down from the discussion, his last answer is from 5 days ago and in the meantime you received a barrage of answers and objections; he also already answered that point for you, and you reset the discussion. He said "That makes a HUGE assumption, however, that the message instance knows exactly how to construct the stream instance composed into it."
This is a huge blocker (one of many others of the same kind) for your proposal as a standard IMO.
He's a developer with a huge experience, he's behind Laminas and at least half the work behind all the HTTP PSRs, so I would hold his opinion in high regard.

> Wow.  This itself is a misrepresentation.  I have responded to each of the points by everyone about my use of PSR except for Larry, with reason.

Again, "with reason". You're giving yourself the right to ignore and dismiss, but anyone that doesn't immediately counter your answers is wrong or proving you right.

> I didn't know that until afterwards.

This (partially) excuses your past behavior. Now you know, and we will not consider you acting in good faith if you will continue forward with using names that are associated to the PHP-FIG.
I want to point to you the fact that, if this wasn't voluntary open source work, this would be the point where lawyers would get involved. But that's not who we are, and not what we want to do. We just want to state clearly that, since you don't want to follow our processes and push forward your ideas through us, we don't want to see affiliations where there isn't none. And you're still welcome to propose your idea through the proper channels if you want.

> I encourage you to really read my responses and present me with counter arguments rather than telling you read through the thread in a cursory manner and decided I'm a bad actor.

Again, you're accusing others (me in this case) of acting in bad faith without proof. I've read this thread and the chat thoroughly, spending more than an hour to understand it all. And I've pointed out (twice now) where I see bad behavior from you.

As I said before, I will now lock this discussion, since it devolved on quote bickering (on all sides) and it's not going anywhere.
Reply all
Reply to author
Forward
This conversation is locked
You cannot reply and perform actions on locked conversations.
0 new messages