Skip to content
This repository was archived by the owner on Dec 1, 2023. It is now read-only.

Commit b9dcb8f

Browse files
updated README.md
1 parent 102bcc8 commit b9dcb8f

File tree

1 file changed

+103
-131
lines changed

1 file changed

+103
-131
lines changed

README.md

Lines changed: 103 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -1,100 +1,131 @@
1-
# sbsedv/input-library
1+
# sbsedv/input-converter
22

3-
A minimal PHP library to nativly support PUT, PATCH and DELETE user input in form of mutlipart/form-data, application/x-www-urlencoded and various JSON types like application/json with complex data structures.
3+
A minimal PHP component to nativly support user input parsing on http methods other than POST.
44

5-
Normally, PHP only parses multipart/form-data and application/x-www-urlencoded on POST requests and does nothing with application/json.
6-
Many libraries, like [symfony/http-foundation](https://symfony.com/doc/current/components/http_foundation.html) with `$request->toArray()`, have limited support for JSON and usually, but not always, only work on POST requests.
5+
PHP natively only supports the parsing of multipart/form-data and application/x-www-urlencoded on POST http requests.
76

8-
The default workarounds are to use the "X-HTTP-METHOD-OVERRIDE" header or a hidden "_method" input field to send requests as method=POST that the server then knows to translate to eg. PUT or PATCH requests.
7+
Many modern web applications also want use / support a) other http methods
8+
like PUT or PATCH and b) other content encodings like JSON or XML.
99

10-
This library provides all you need to nativly support these kinds of requests, including complex data structures like nested Arrays and Objects. Because internally this library uses the PHP native functions [json_decode](https://www.php.net/manual/en/function.json-decode) and [parse_str](https://www.php.net/manual/en/function.parse-str) (multpart/form-data gets translated to x-www-urlencoded), complex data structures are only limited by what those functions support.
10+
This component provides a very simple and extensible object oriented api to support just that.
11+
12+
Internally this component uses the PHP native functions [json_decode](https://www.php.net/manual/en/function.json-decode) and [parse_str](https://www.php.net/manual/en/function.parse-str) (multpart/form-data gets "translated" to x-www-urlencoded) and therefore complex data structures (arrays and objects) are only limited by what those functions support. <br/>
13+
This effectifly means that HTMLForms like the following are `FULLY supported`.
14+
15+
```html
16+
<form method="PUT">
17+
<select name="select[]" multiple>
18+
...
19+
</select>
20+
21+
<input type="text" name="text" />
22+
23+
<input type="text" name="obj[key1]" />
24+
<input type="text" name="obj[key2]" />
25+
<select name="obj[key3][]" multiple>
26+
...
27+
</select>
28+
</form>
29+
```
1130

1231
---
1332

1433
## **How it Works**
1534

16-
You should call this library as early as possible in your application.
35+
You should instantiate and call this component as early in your app lifecycle as possible.
1736

18-
You **CAN** pass a [PSR-7](https://www.php-fig.org/psr/psr-7/) or [HTTP-Foundation](https://symfony.com/doc/current/components/http_foundation.html) to the constructor and the library will make use of that.
19-
If you do not pass anything to the constructor, the library uses PHPs `$_SERVER` global.
37+
You **MUST** pass either a [PSR-7](https://www.php-fig.org/psr/psr-7/) or [HTTP-Foundation](https://symfony.com/doc/current/components/http_foundation.html) request object to the "convert" method.
2038

2139
```php
2240
<?php declare(strict_types=1);
2341

24-
use SBSEDV\InputLibrary\InputLibrary;
25-
use SBSEDV\InputLibrary\Transformer\FormData;
26-
use SBSEDV\InputLibrary\Transformer\JSON;
27-
use SBSEDV\InputLibrary\Transformer\UrlEncoded;
28-
29-
// PUT /test HTTP/1.1
30-
// HOST: example.com
31-
// Content-Type: application/json
32-
// {"key": "value", "array": ["value1","value2"]}
33-
//
34-
// === OR ===
35-
//
36-
// Content-Type: application/x-www-urlencoded
37-
// key=value&array[]=value1&array[]=value2
38-
//
39-
// === OR ===
40-
//
41-
// Content-Type: multipart/form-data; boundary=----WebKitFormBoundary1fownfown
42-
// ------WebKitFormBoundary1fownfown
43-
// Content-Disposition: form-data; name="key"
44-
// value
45-
// ------WebKitFormBoundary1fownfown
46-
// Content-Disposition: form-data; name="array[]"
47-
// value1
48-
// ------WebKitFormBoundary1fownfown
49-
// Content-Disposition: form-data; name="array[]"
50-
// value2
51-
52-
/**
53-
* You can pass an instance of
54-
* Psr\Http\Message\ServerRequestInterface
55-
* OR
56-
* Symfony\Component\HttpFoundation\Request
57-
* to the constructor.
58-
*
59-
* Otherwise the library uses PHP globals.
60-
*
61-
* You can als set / remove the request object
62-
* via setRequest in case you are having problems
63-
* with your container builder.
64-
*
65-
* @return SBSEDV\InputLibrary\ParsedInput
66-
*/
67-
$parseInput = (new InputLibrary())
68-
->registerTransformers(
69-
new JSON([
70-
'application/json',
71-
'application/ld+json'
72-
]), // support multiple json types
73-
new UrlEncoded(['PUT', 'PATCH']), // allow only PUT and PATCH
74-
new FormData() // default options
75-
)->run();
42+
use SBSEDV\Component\InputConverter\InputConverter;
43+
use SBSEDV\Component\InputConverter\ParsedInput;
44+
45+
try {
46+
/** @var ParsedInput $parsedInput */
47+
$parsedInput = (new InputConverter())
48+
->addConverter(...) // your converter instance
49+
->convert($request);
50+
} catch (MalformedContentException $e) {
51+
// a converter supported the request
52+
// but encountered an error while parsing
53+
54+
http_status_code(400);
55+
exit();
56+
} catch (UnsupportedRequestException) {
57+
// no converter supported the request
58+
}
59+
7660

7761
// update $_POST and $_FILES with parsed values
78-
$parseInput->toGlobals(): void;
79-
// populate $request->request and $request->files
80-
$parseInput->toHttpFoundation(
81-
Symfony\Component\HttpFoundation\Request $request
82-
): void;
62+
$parseInput->toGlobals();
63+
64+
// OR populate $request->request and $request->files
65+
$parseInput->applyOnHttpFoundationRequest($request);
8366

84-
// or access the data directly
67+
// OR access the data directly
8568
$values = $parseInput->getValues(): array; // like $_POST
8669
$files = $fileInput->getFiles(): array // like $_FILES
8770
```
8871

8972
---
9073

91-
### **CAUTION WITH FILE UPLOADS**:
74+
## **Converters**
75+
76+
The actual parsing is handled by converter classes that implement
77+
[SBSEDV\Component\InputConverter\Converter\ConverterInterface](src/Converter/ConverterInterface.php).
78+
79+
You can always implement your own converter.
80+
81+
By default we support three customisable converters:
82+
83+
### `SBSEDV\Component\InputConverter\Converter\UrlEncoded`
84+
85+
Via its constructor you can influence which content types and http methods it supports.
86+
87+
```php
88+
public function __construct(
89+
array $contentTypes = ['application/x-www-urlencoded'],
90+
array $methods = ['PUT', 'PATCH', 'DELETE']
91+
);
92+
```
93+
94+
---
95+
96+
### `SBSEDV\Component\InputConverter\Converter\JSON`
97+
98+
Via its constructor you can influence which content types and http methods it supports.
99+
100+
```php
101+
public function __construct(
102+
array $contentTypes = ['application/json'],
103+
array $methods = ['POST', 'PUT', 'PATCH', 'DELETE']
104+
);
105+
```
106+
107+
---
108+
109+
### `SBSEDV\Component\InputConverter\Converter\FormData`
110+
111+
Via its constructor you can influence which content types and http methods it supports.
112+
113+
Internally this uses the [riverline/multipart-parser](https://github.com/Riverline/multipart-parser) library for parsing.
114+
115+
```php
116+
public function __construct(
117+
array $methods = ['PUT', 'PATCH', 'DELETE'],
118+
bool $fileSupport = false
119+
);
120+
```
121+
122+
#### **CAUTION WITH FILE UPLOADS**:
92123

93-
Even though file uploads via mulitpart/form-data are fully supported, they are **NOT** recommended because the whole file will be loaded into memory which may become a problem with large files and shared hosting plans. You should instead use POST request for file uploads and let PHP handle that mess.
124+
Even though file uploads via mulitpart/form-data are fully supported, they are **NOT** recommended because the whole file will be loaded into memory. You should instead use POST request for file uploads and let PHP handle that mess natively.
94125

95-
#### ***COMPATIBILITY***:
126+
#### **_COMPATIBILITY_**:
96127

97-
The returned file format is not 100 percent compatibile with the native [$_FILES](https://www.php.net/manual/en/features.file-upload.post-method.php#example-420) global.
128+
Also, the returned file format is not 100 percent compatibile with the native [$\_FILES](https://www.php.net/manual/en/features.file-upload.post-method.php#example-420) global.
98129

99130
If you upload an array / of images like:
100131

@@ -136,63 +167,4 @@ $_FILES_ = [
136167
];
137168
```
138169

139-
For sanity reasons, this library returns the **expected** behaviour.
140-
141-
---
142-
143-
## **Transformers**
144-
145-
The actual parsing and extracting is handled by `Transformer` classes that implement `SBSEDV\InputLibrary\TransformerInterface`.
146-
147-
You can always implement your own transformer to handle your custom content types and register it with the library via the `SBSEDV\InputLibrary\InputLibrary::registerTransformer` method.
148-
149-
By default, this library comes with three transformers:
150-
151-
##### `SBSEDV\InputLibrary\Transformer\UrlEncoded`
152-
153-
This transformer handles application/x-www-urlencoded.
154-
Under the hood, this uses PHPs native [parse_str](https://www.php.net/manual/en/function.parse-str) function.
155-
Via its constructor you can influence on which methods it should work.
156-
157-
```php
158-
// SBSEDV\InputLibrary\Transformer\UrlEncoded
159-
160-
public function __construct(
161-
array $methods = ['PUT', 'PATCH', 'DELETE']
162-
);
163-
```
164-
165-
##### `SBSEDV\InputLibrary\Transformer\JSON`
166-
167-
This transformer handles JSON.
168-
Internally this uses PHPs native [json_decode](https://www.php.net/manual/en/function.json-decode) function.
169-
Via its constructor you can influence on which content-types and methods it should work.
170-
171-
Because PHP does not parse JSON nativly, this also registers for the POST http method.
172-
173-
```php
174-
// SBSEDV\InputLibrary\Transformer\JSON
175-
176-
public function __construct(
177-
array $contentTypes = ['application/json'],
178-
array $methods = ['POST', 'PUT', 'PATCH', 'DELETE']
179-
);
180-
```
181-
182-
##### `SBSEDV\InputLibrary\Transformer\FormData`
183-
184-
This transformer handles mulitpart/form-data and is by far the most complicated, but also the most convenient because of JavaScripts awesome [FormData API](https://developer.mozilla.org/en-US/docs/Web/API/FormData).
185-
186-
Internally this uses the awesome [riverline/multipart-parser](https://github.com/Riverline/multipart-parser) library for parsing. Then, those key-value pairs are concatenated to a x-www-urlencoded string and then passed to the native [parse_str](https://www.php.net/manual/en/function.parse-str) function to keep complex data structures.
187-
188-
189-
Via its constructor you can influence on which methods it should work and if file uploads should be supported (defaults to false).
190-
191-
```php
192-
// SBSEDV\InputLibrary\Transformer\FormData
193-
194-
public function __construct(
195-
array $methods = ['PUT', 'PATCH', 'DELETE'],
196-
bool $fileSupport = false
197-
);
198-
```
170+
For sanity reasons we return the **expected** behaviour.

0 commit comments

Comments
 (0)