Skip to content

A minimal PHP library to nativly support PUT, PATCH and DELETE user input in form of mutlipart/form-data, application/x-www-form-urlencoded and various JSON types like application/json with complex data structures (nested html forms).

License

Notifications You must be signed in to change notification settings

paggy-project/php-input-converter

 
 

Repository files navigation

PHPStan PHPUnit

sbsedv/input-converter

A minimal PHP component to nativly support user input parsing on http methods other than POST.

PHP natively only supports the parsing of multipart/form-data and application/x-www-form-urlencoded on POST http requests.

Many modern web applications also want use / support a) other http methods like PUT or PATCH and b) other content encodings like JSON or XML.

This component provides a very simple and extensible object oriented api to support just that.

Internally this component uses the PHP native functions json_decode and parse_str (multpart/form-data gets "translated" to x-www-form-urlencoded) and therefore complex data structures (arrays and objects) are only limited by what those functions support.
This effectifly means that HTMLForms like the following are FULLY supported.

<form method="PUT">
    <select name="select[]" multiple>
        ...
    </select>

    <input type="text" name="text" />

    <input type="text" name="obj[key1]" />
    <input type="text" name="obj[key2]" />
    <select name="obj[key3][]" multiple>
        ...
    </select>
</form>

How it Works

You should instantiate and call this component as early in your app lifecycle as possible.

You MUST pass either a PSR-7 or HTTP-Foundation request object to the "convert" method.

<?php declare(strict_types=1);

use SBSEDV\InputConverter\InputConverter;
use SBSEDV\InputConverter\ParsedInput;

try {
    /** @var ParsedInput $parsedInput */
    $parsedInput = (new InputConverter())
        ->addConverter(...) // your converter instance
        ->convert($request);
} catch (MalformedContentException $e) {
    // a converter supported the request
    // but encountered an error while parsing

    http_status_code(400);
    exit();
} catch (UnsupportedRequestException) {
    // no converter supported the request
}

// access the data directly
$values = $parseInput->getValues(): array; // like $_POST
$files = $fileInput->getFiles(): array // like $_FILES

// and add them to your http-foundation / psr7 implementation
foreach ($parsedInput->getValues() as $key => $value) {
    // http-foundation
    $request = $request->request->set($key, $value);
}

Converters

The actual parsing is handled by converter classes that implement SBSEDV\InputConverter\Converter\ConverterInterface.

You can always implement your own converter.

By default we support three customisable converters:

SBSEDV\InputConverter\Converter\UrlEncodedConverter

Via its constructor you can influence which http methods it supports.

public function __construct(
    array $methods = ['PUT', 'PATCH', 'DELETE']
);

SBSEDV\InputConverter\Converter\JsonConverter

Via its constructor you can influence which content types and http methods it supports.

public function __construct(
    array $contentTypes = ['application/json'],
    array $methods = ['POST', 'PUT', 'PATCH', 'DELETE']
);

SBSEDV\InputConverter\Converter\FormDataConverter

Via its constructor you can influence which content types and http methods it supports.

Internally this uses the riverline/multipart-parser library for parsing.

public function __construct(
    array $methods = ['PUT', 'PATCH', 'DELETE'],
    bool $fileSupport = false
);

CAUTION WITH FILE UPLOADS:

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.

COMPATIBILITY:

Also, the returned file format is not compatibile with the native $_FILES global.

If you upload an array / of images like:

<input type="file" name="pictures[test1]" />
<input type="file" name="pictures[test2]" />

PHP has a very, lets say not friendly way of sorting the array:

// Expected behaviour
$_FILES_ = [
    'pictures' => [
        'test1' => [
            'name' => 'test.png',
            'type' => 'image/png',
            'tmp_name' => '/tmp/123456',
            'error' => 0,
            'size' => 1234
        ],
        'test2' => [
            ...
        ]
    ]
];

// Actual behaviour
$_FILES_ = [
    'name' => [
        'test1' => 'what.png',
        'test2' => 'the_heck.jpg'
    ],
    'type' => [
        'test1' => 'image/png',
        'test2' => 'image/jpeg'
    ],
    ...
];

We return the much more friendly expected behaviour.

About

A minimal PHP library to nativly support PUT, PATCH and DELETE user input in form of mutlipart/form-data, application/x-www-form-urlencoded and various JSON types like application/json with complex data structures (nested html forms).

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • PHP 100.0%