Yii2: Add support for PSR-7

Created on 11 Apr 2016  Â·  36Comments  Â·  Source: yiisoft/yii2

Since PSR-7 is now accepted, it would be great to have it supported in Yii2 for both yii\web\Request and yii\web\Response.

Some options:

  1. Implement Psr\Http\Message\ServerRequestInterface in yii\web\Request and implement Psr\Http\Message\ResponseInterface in yii\web\Response.
  2. Add methods Request::getPsr() and Response::setPsr() methods that will return objects that are implementing this interfaces.

PHP world is moving to middleware approach (for example thephpleague/oauth2-server), and it would be great to support this in Yii2.

under discussion enhancement

Most helpful comment

@sjelfull under discussion but it's highly requested feature.

All 36 comments

Thats a BC Break and its planned for https://github.com/yiisoft/yii2/wiki/Ideas-for-2.1

@Faryshta, thanks for pointing this out. Ideas for 2.1 are looking more like ideas for 3.0 (according to semver) :)

who is semver?

Yii2 does not follow semver, so this change is possible in 2.1, I guess

PHP world is moving to middleware approach (for example thephpleague/oauth2-server), and it would be great to support this in Yii2.

@kop, where is middleware support in oauth2-server?
UPD: I find it https://github.com/thephpleague/oauth2-server/tree/V5-WIP

@Faryshta @SilverFire If Yii2 has adopted Composer (which is has) it would prevent a lot of headache and misunderstandings to follow semver.

Idea: Build out a PSR-7 complaint Request/Response interface separate from the current interface. Then both functionality classes are available but not creating BC changes.

@davidjeddy composer can work wihout semver. Its not a requirement.

If Yii2 has adopted Composer (which is has) it would prevent a lot of headache and misunderstandings to follow semver.

Semver works fine for simple libraries, where impact of change is more predictable, not so much for complex frameworks like Yii is. Also Yii is basiacally following the ideas of semver but with a shift of the version number so the major defines the branch of framework, which have different code bases, e.g. 1 vs 2. and the following number is the major semver version.
I suggest to read this document on why we are not following strict semver:
https://github.com/yiisoft/yii2/blob/master/docs/internals/versions.md

@Faryshta @cebe Very true, and very good points. So back to the other idea: 2.1 as a BC change or implementing a second interface of request/response classes.

I found this article about PSR7 and I think its worth reading for this issue. https://evertpot.com/psr-7-issues/

The main problem with implementing PSR7 will be the inmutability which would break the way yii2 handles events and behaviors.

@Faryshta, it depends on the way in which we decide to support it.
If we implement something like getPsr() that returns a "copy" of the current request / response in the form of an immutable PSR-7 implementation object, then that would be fine.

I agree that changing the request / response objects themselves to implement PSR-7 would cause big backwards compatibility issues.

@SamMousa but even if we do that

things like Yii::$app->response->getPsr()->withHeaders(...) would be meaningless since the object stored in the $response object wouldn't get affected.

I think that if we implement something like this then we should talk about the inmutability and how it affects the yii2 events, behaviors and controllers.

If we implement something like getPsr() that returns a "copy" of the current request / response in the form of an immutable PSR-7 implementation object, then that would be fine.

I can see no sense in such approach. In order to get any benefit of following PSR standard the componets should directly implement its interfaces. The entire goal of PSR is making classes from different libraries to be compatible with each other.
The expected behavior: if I replace yii\web\Request with class picked up from other library implementing PSR interface - all my project code should work without error or warning.

If we will hide PSR compatibale objects by some wrapper - we will gain no benefit from it.

@klimov-paul There are other usages that are served by this approach.

Suppose I have some kind of middleware that needs a request and gives me a response:

$yiiRequest = Yii::$app->request;
$yiiResponse = Yii::$app->response;

$middleWare = new MiddleWare();
$psrResponse = $middleWare->run($yiiRequest->getPsr(), $yiiResponse->getPsr());

$yiiResponse->setPsr($psrResponse);

In any case the whole concept of request / response being an application component clashes with immutability.

@SamMousa, with your example we should not support PSR at all.

I can say just the same way, you should wrap your MiddleWare into some class, which will perfrom convertion from PSR to Yii and vice versa.

You may able to compose such converter even now.

The things you are talking about is not the goals of PSR.

@klimov-paul I agree about it not being the main goal of PSR.

It could be a temporary implementation so people can already start using PSR, until a next big BC breaking release comes along where the whole component is replaced with a PSR implementation.

And yes obviously I can wrap the calling code for my MiddleWare so it converts to / from PSR, but since the PSR is stable it would be nice to have that in the Yii core. (It could easily be released as a separate library though).

I think fully switching over to immutability would be best, but is not something you should do in a minor upgrade.

2.1 isn't minor. We're soon going to switch to 4 digit semver to avoid confusion i.e. 2.1.a.b where a are introducing new features (current releases style) and b are strictly patch releases which we, in fact, rarely have.

If it's possible to cover this issue for 2.1, that would be great, if not, there will be 2.2 eventually. We aren't going to do 3.0 right away breaking everything same way as 1.1→2.0 did.

How would you like to handle updates to the response object?
Ideally the response object would always be returned / stored locally instead of globally accessible?
Implementation shouldn't be too hard but we need to make some design decisions.

Note we could just implement PSR-7 for Request at the start. The request component would then contain the "original" that was created from the PHP globals. If you alter it you get a new local copy and the "global" copy is never updated (unless you do it manually via setComponent).

Partially implementing PSR-7 doesn't make sense to me. Better to implement both request and response.

I think we may remove request/response from global scope safely. Environment should be dealt with in controller anyway.

How do we handle requests? For example from RateLimiter:

$this->addRateLimitHeaders($response, $limit, 0, $window);
throw new TooManyRequestsHttpException($this->errorMessage);

First line updates the response object (that could easily be updated to use the new one). But how will the exception handler get access to the new headers?
Could we add an optional $response param to HttpException ?

Could we add an optional $response param to HttpException ?

Either that or we can pass it to the handler.

If we pass it to the handler than we still need a "global" response object.

$response = $this->addRateLimitHeaders($response, $limit, 0, $window);
throw new TooManyRequestsHttpException($this->errorMessage);

Right. Then that leaves only one option.

@samdark if there is only one way to work. Wouldn't that make the framework hard to extend?

For example in the yii\rest\ActiveController class we have the beforeAction(), action and afterAction() modifying the response headers and how its formatted. Then the response has to be passed and rewritten all the time. How would a behavior acting on the ActiveController::EVENT_BEFORE_ACTION work?

Resolved via #14701

Would be great if we could get a tiny example in the guide.

https://github.com/yiisoft/yii2/wiki/PSR-adoption does not mention any plans for HTTP Middlewares. Is it planned?

@sjelfull under discussion but it's highly requested feature.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dhiman252 picture dhiman252  Â·  44Comments

SamMousa picture SamMousa  Â·  55Comments

njasm picture njasm  Â·  44Comments

samdark picture samdark  Â·  52Comments

alexraputa picture alexraputa  Â·  53Comments