{
    "href": "/post/2021/11/09/sapien-requestresponse-objects-for-php-81/",
    "relId": "2021/11/09/sapien-requestresponse-objects-for-php-81",
    "title": "Sapien: Request/Response Objects for PHP 8.1",
    "author": "pmjones",
    "tags": [
        {
            "href": "/tag/programming/",
            "relId": "programming",
            "title": "Programming",
            "author": null,
            "created": null,
            "updated": [],
            "markup": "markdown"
        },
        {
            "href": "/tag/php/",
            "relId": "php",
            "title": "PHP",
            "author": null,
            "created": null,
            "updated": [],
            "markup": "markdown"
        },
        {
            "href": "/tag/sapien/",
            "relId": "sapien",
            "title": "Sapien",
            "author": null,
            "created": "2021-11-09 16:57:39 UTC",
            "updated": [
                "2021-11-09 16:57:39 UTC"
            ],
            "markup": "markdown"
        }
    ],
    "created": "2021-11-09 16:57:39 UTC",
    "updated": [
        "2021-11-09 16:57:39 UTC",
        "2021-11-09 17:08:06 UTC",
        "2021-11-09 20:04:45 UTC"
    ],
    "markup": "markdown",
    "html": "<p>I am happy to announce the 1.0.0 release of <a href=\"http://sapienphp.com\">Sapien</a>. Like its predecessor <a href=\"http://pecl.php.net/request\">ext-request</a>, Sapien provides server API (SAPI) <em>Request</em> and <em>Response</em> objects -- but in userland, for PHP 8.1.</p>\n<p>The Sapien classes do not model HTTP messages per se. Instead, the <a href=\"https://sapienphp.com/1.x/request/overview.html\"><em>Request</em></a> is a readonly value object composed of other readonly value objects representing the PHP superglobals and data structures derived from or composed of them. Similarly, the <a href=\"https://sapienphp.com/1.x/response/overview.html\"><em>Response</em></a> is a wrapper around and buffer for the various response-related global PHP functions.</p>\n<p>Read more about Sapien at <a href=\"http://sapienphp.com\">http://sapienphp.com</a>.</p>\n<hr>\n<p>The Sapien project has a long history, <a href=\"https://paul-m-jones.com/post/2016/11/22/the-php-7-request-extension/\">starting about 5 years ago</a> as PECL extension in C. It had a second major version bump as part of <a href=\"https://wiki.php.net/rfc/request_response\">an RFC to PHP itself</a>, which did not pass.</p>\n<p>In <a href=\"https://externals.io/message/109563\">the after-action report on the failed RFC</a>, I recorded the prevailing opinion that things like request and response objects should stay in userland. The problem with that, in the case of ext-request, was that readonly immutable objects were possible more effectively in C code than in userland PHP.</p>\n<p>However, with the advent of PHP 8.1 and <a href=\"https://php.watch/versions/8.1/readonly\"><code>readonly</code></a> properties, all the functionality of the C code is now available in userland PHP. In a way, that means Sapien is a third version of ext-request, but fully in userland.</p>\n<p>Sapien makes extensive use of <code>readonly</code>, presenting a <a href=\"https://sapienphp.com/1.x/request/\"><em>Request</em></a> value object that is designed to be unchanging after instantiation. And because it's much easier to work in PHP than in C, there are many more value objects composed into the <em>Request</em> than in the C versions, such as:</p>\n<ul>\n<li>\n<p><a href=\"https://sapienphp.com/1.x/request/content.html\"><em>Content</em></a>, built up from various content-related headers and the request body itself</p>\n</li>\n<li>\n<p><a href=\"https://sapienphp.com/1.x/request/uploads.html\"><em>Upload</em></a>, including the new <a href=\"https://php.watch/versions/8.1/%24_FILES-full-path\"><code>full_path</code></a> value from <code>$_FILES</code> entries.</p>\n</li>\n<li>\n<p><a href=\"https://sapienphp.com/1.x/request/url.html\"><em>Url</em></a>, computed from the various <code>$_SERVER</code> values</p>\n</li>\n<li>\n<p><a href=\"https://sapienphp.com/1.x/request/accept.html\"><em>Accept</em></a> value object collections for <em>Type</em>, <em>Charset</em>, <em>Encoding</em>, and <em>Language</em></p>\n</li>\n<li>\n<p><a href=\"https://sapienphp.com/1.x/request/forward.html#1-1-9-1\"><em>XForwarded</em></a>, distilled from the various <code>x-forwarded-*</code> headers</p>\n</li>\n<li>\n<p><a href=\"https://sapienphp.com/1.x/request/forward.html#1-1-9-2\"><em>Forwarded</em></a> value object collections derived from the <code>Forwarded</code> header</p>\n</li>\n<li>\n<p><a href=\"https://sapienphp.com/1.x/request/authorization.html\"><em>Authorization\\Scheme</em></a> value objects for basic, bearer, and digest authorization</p>\n</li>\n</ul>\n<p>The <em>Response</em> is fundamentally the same as it was in ext-request v1, though the custom file- and JSON-specific response logic has been extracted to <a href=\"https://sapienphp.com/1.x/response/special.html\">specialized classes</a>. Even so, the generic response is capable of handling <a href=\"https://sapienphp.com/1.x/response/sending.html#1-2-8-1\">all sorts of content</a>, including iterables and resources.</p>\n<p>So, if you're starting a new PHP 8.1 project, or refactoring a legacy system to PHP 8.1, try out <a href=\"http://sapienphp.com\">Sapien</a>, because request and response objects make life so much easier.</p>\n"
}
