Skip to content

Commit 4ba875b

Browse files
committed
Implementing immutability in messages
Marked all classes and setters as immutable. All setters have language indicating they MUST be implemented to keep immutable state of the object, and MUST return a new instance with the modified values.
1 parent 9ffea55 commit 4ba875b

File tree

4 files changed

+96
-28
lines changed

4 files changed

+96
-28
lines changed

src/MessageInterface.php

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
* from a server to a client. This interface defines the methods common to
88
* each.
99
*
10+
* Messages are considered immutable; all methods that might change state MUST
11+
* be implemented such that they retain the internal state of the current
12+
* message and return a new instance that contains the changed state.
13+
*
1014
* @link http://www.ietf.org/rfc/rfc7230.txt
1115
* @link http://www.ietf.org/rfc/rfc7231.txt
1216
*/
@@ -27,8 +31,12 @@ public function getProtocolVersion();
2731
* The version string MUST contain only the HTTP version number (e.g.,
2832
* "1.1", "1.0").
2933
*
34+
* This method MUST be implemented in such a way as to retain the
35+
* immutability of the message, and MUST return a new instance that has the
36+
* new protocol version.
37+
*
3038
* @param string $version HTTP protocol version
31-
* @return void
39+
* @return MessageInterface
3240
*/
3341
public function setProtocolVersion($version);
3442

@@ -95,9 +103,13 @@ public function getHeaderLines($header);
95103
* The header name is case-insensitive. The header values MUST be a string
96104
* or an array of strings.
97105
*
106+
* This method MUST be implemented in such a way as to retain the
107+
* immutability of the message, and MUST return a new instance that has the
108+
* new and/or updated header and value.
109+
*
98110
* @param string $header Header name
99111
* @param string|string[] $value Header value(s).
100-
* @return void
112+
* @return MessageInterface
101113
* @throws \InvalidArgumentException for invalid header names or values.
102114
*/
103115
public function setHeader($header, $value);
@@ -108,18 +120,26 @@ public function setHeader($header, $value);
108120
* Existing values for the specified header will be maintained. The new
109121
* value(s) will be appended to the existing list.
110122
*
123+
* This method MUST be implemented in such a way as to retain the
124+
* immutability of the message, and MUST return a new instance that has the
125+
* new header and/or value.
126+
*
111127
* @param string $header Header name to add
112128
* @param string|string[] $value Header value(s).
113-
* @return void
129+
* @return MessageInterface
114130
* @throws \InvalidArgumentException for invalid header names or values.
115131
*/
116132
public function addHeader($header, $value);
117133

118134
/**
119135
* Remove a specific header by case-insensitive name.
120136
*
137+
* This method MUST be implemented in such a way as to retain the
138+
* immutability of the message, and MUST return a new instance that removes
139+
* the named header.
140+
*
121141
* @param string $header HTTP header to remove
122-
* @return void
142+
* @return MessageInterface
123143
*/
124144
public function removeHeader($header);
125145

@@ -135,8 +155,12 @@ public function getBody();
135155
*
136156
* The body MUST be a StreamableInterface object.
137157
*
158+
* This method MUST be implemented in such a way as to retain the
159+
* immutability of the message, and MUST return a new instance that has the
160+
* new body stream.
161+
*
138162
* @param StreamableInterface $body Body.
139-
* @return void
163+
* @return MessageInterface
140164
* @throws \InvalidArgumentException When the body is not valid.
141165
*/
142166
public function setBody(StreamableInterface $body);

src/RequestInterface.php

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,18 @@
55
/**
66
* Representation of an outgoing, client-side request.
77
*
8-
* Per the HTTP specification, this interface includes both accessors for
9-
* and mutators for the following:
8+
* Per the HTTP specification, this interface includes properties for
9+
* each of the following:
1010
*
1111
* - Protocol version
1212
* - HTTP method
1313
* - URL
1414
* - Headers
1515
* - Message body
1616
*
17-
* As the request CAN be built iteratively, the interface allows
18-
* mutability of all properties.
17+
* Requests are considered immutable; all methods that might change state MUST
18+
* be implemented such that they retain the internal state of the current
19+
* message and return a new instance that contains the changed state.
1920
*/
2021
interface RequestInterface extends MessageInterface
2122
{
@@ -34,8 +35,12 @@ public function getMethod();
3435
* method names are case-sensitive and thus implementations SHOULD NOT
3536
* modify the given string.
3637
*
38+
* This method MUST be implemented in such a way as to retain the
39+
* immutability of the message, and MUST return a new instance that has the
40+
* changed request method.
41+
*
3742
* @param string $method Case-insensitive method.
38-
* @return void
43+
* @return RequestInterface
3944
* @throws \InvalidArgumentException for invalid HTTP methods.
4045
*/
4146
public function setMethod($method);
@@ -78,9 +83,13 @@ public function getAbsoluteUri();
7883
* When setting the absolute URI, the url (see getUrl() and setUrl()) MUST
7984
* be updated.
8085
*
86+
* This method MUST be implemented in such a way as to retain the
87+
* immutability of the message, and MUST return a new instance that has the
88+
* changed URI and updated URL.
89+
*
8190
* @link http://tools.ietf.org/html/rfc3986#section-4.3
8291
* @param string $uri Absolute request URI.
83-
* @return void
92+
* @return RequestInterface
8493
* @throws \InvalidArgumentException If the URI is invalid.
8594
*/
8695
public function setAbsoluteUri($uri);
@@ -106,9 +115,13 @@ public function getUrl();
106115
* When setting the URL, the absolute URI (see getAbsoluteUri() and
107116
* setAbsoluteUri()) MUST be updated.
108117
*
118+
* This method MUST be implemented in such a way as to retain the
119+
* immutability of the message, and MUST return a new instance that has the
120+
* changed URL and updated absolute URI.
121+
*
109122
* @link http://tools.ietf.org/html/rfc7230#section-5.3
110123
* @param string $url Request URL, with path and optionally query string.
111-
* @return void
124+
* @return RequestInterface
112125
* @throws \InvalidArgumentException If the URL is invalid.
113126
*/
114127
public function setUrl($url);

src/ResponseInterface.php

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,17 @@
55
/**
66
* Representation of an outgoing, server-side response.
77
*
8-
* Per the HTTP specification, this interface includes both accessors for
9-
* and mutators for the following:
8+
* Per the HTTP specification, this interface includes properties for
9+
* each of the following:
1010
*
1111
* - Protocol version
1212
* - Status code and reason phrase
1313
* - Headers
1414
* - Message body
1515
*
16-
* As the response CAN be built iteratively, the interface allows
17-
* mutability of all properties.
16+
* Responses are considered immutable; all methods that might change state MUST
17+
* be implemented such that they retain the internal state of the current
18+
* message and return a new instance that contains the changed state.
1819
*/
1920
interface ResponseInterface extends MessageInterface
2021
{
@@ -35,12 +36,17 @@ public function getStatusCode();
3536
* to the RFC 7231 or IANA recommended reason phrase for the response's
3637
* Status-Code.
3738
*
39+
* This method MUST be implemented in such a way as to retain the
40+
* immutability of the message, and MUST return a new instance that has the
41+
* updated status and reason phrase.
42+
*
3843
* @link http://tools.ietf.org/html/rfc7231#section-6
3944
* @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
4045
* @param integer $code The 3-digit integer result code to set.
4146
* @param null|string $reasonPhrase The reason phrase to use with the
4247
* provided status code; if none is provided, implementations MAY
4348
* use the defaults as suggested in the HTTP specification.
49+
* @return ResponseInterface
4450
* @throws \InvalidArgumentException For invalid status code arguments.
4551
*/
4652
public function setStatus($code, $reasonPhrase = null);

src/ServerRequestInterface.php

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
/**
66
* Representation of an incoming, server-side HTTP request.
77
*
8-
* Per the HTTP specification, this interface includes accessors for
9-
* the following:
8+
* Per the HTTP specification, this interface includes properties for
9+
* each of the following:
1010
*
1111
* - Protocol version
1212
* - HTTP method
@@ -24,16 +24,21 @@
2424
* - Deserialized body parameters (generally from $_POST)
2525
*
2626
* $_SERVER and $_FILES values MUST be treated as immutable, as they represent
27-
* application state at the time of request. The other values SHOULD be
28-
* mutable, as they can be restored from $_SERVER, $_FILES, or the request
29-
* body, and may need treatment during the application (e.g., body parameters
30-
* may be deserialized based on content type).
27+
* application state at the time of request; as such, no methods are provided
28+
* to allow modification of those values. The other values provide such methods,
29+
* as they can be restored from $_SERVER, $_FILES, or the request body, and may
30+
* need treatment during the application (e.g., body parameters may be
31+
* deserialized based on content type).
3132
*
3233
* Additionally, this interface recognizes the utility of introspecting a
3334
* request to derive and match additional parameters (e.g., via URI path
3435
* matching, decrypting cookie values, deserializing non-form-encoded body
3536
* content, matching authorization headers to users, etc). These parameters
36-
* are stored in an "attributes" property, which MUST be mutable.
37+
* are stored in an "attributes" property.
38+
*
39+
* Requests are considered immutable; all methods that might change state MUST
40+
* be implemented such that they retain the internal state of the current
41+
* message and return a new instance that contains the changed state.
3742
*/
3843
interface ServerRequestInterface extends RequestInterface
3944
{
@@ -69,8 +74,12 @@ public function getCookieParams();
6974
* be compatible with the structure of $_COOKIE. Typically, this data will
7075
* be injected at instantiation.
7176
*
77+
* This method MUST be implemented in such a way as to retain the
78+
* immutability of the message, and MUST return a new instance that has the
79+
* updated cookie values.
80+
*
7281
* @param array $cookies Array of key/value pairs representing cookies.
73-
* @return void
82+
* @return ServerRequestInterface
7483
*/
7584
public function setCookieParams(array $cookies);
7685

@@ -102,9 +111,13 @@ public function getQueryParams();
102111
* Setting query string arguments MUST NOT change the URL stored by the
103112
* request, nor the values in the server params.
104113
*
114+
* This method MUST be implemented in such a way as to retain the
115+
* immutability of the message, and MUST return a new instance that has the
116+
* updated query string arguments.
117+
*
105118
* @param array $query Array of query string arguments, typically from
106119
* $_GET.
107-
* @return void
120+
* @return ServerRequestInterface
108121
*/
109122
public function setQueryParams(array $query);
110123

@@ -143,8 +156,12 @@ public function getBodyParams();
143156
* a JSON payload, this method could be used to inject the deserialized
144157
* parameters.
145158
*
159+
* This method MUST be implemented in such a way as to retain the
160+
* immutability of the message, and MUST return a new instance that has the
161+
* updated body parameters.
162+
*
146163
* @param array $params The deserialized body parameters.
147-
* @return void
164+
* @return ServerRequestInterface
148165
*/
149166
public function setBodyParams(array $params);
150167

@@ -181,9 +198,13 @@ public function getAttribute($attribute, $default = null);
181198
* This method allows setting request attributes, as described in
182199
* getAttributes().
183200
*
201+
* This method MUST be implemented in such a way as to retain the
202+
* immutability of the message, and MUST return a new instance that has the
203+
* updated attributes.
204+
*
184205
* @see getAttributes()
185206
* @param array $attributes Attributes derived from the request.
186-
* @return void
207+
* @return ServerRequestInterface
187208
*/
188209
public function setAttributes(array $attributes);
189210

@@ -193,10 +214,14 @@ public function setAttributes(array $attributes);
193214
* This method allows setting a single derived request attribute as
194215
* described in getAttributes().
195216
*
217+
* This method MUST be implemented in such a way as to retain the
218+
* immutability of the message, and MUST return a new instance that has the
219+
* updated attribute.
220+
*
196221
* @see getAttributes()
197222
* @param string $attribute The attribute name.
198223
* @param mixed $value The value of the attribute.
199-
* @return void
224+
* @return ServerRequestInterface
200225
*/
201226
public function setAttribute($attribute, $value);
202227
}

0 commit comments

Comments
 (0)