I am happy to announce the 1.0.0 release of Sapien. Like its predecessor ext-request, Sapien provides server API (SAPI) Request and Response objects -- but in userland, for PHP 8.1.

The Sapien classes do not model HTTP messages per se. Instead, the Request 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 Response is a wrapper around and buffer for the various response-related global PHP functions.

Read more about Sapien at http://sapienphp.com.


The Sapien project has a long history, starting about 5 years ago as PECL extension in C. It had a second major version bump as part of an RFC to PHP itself, which did not pass.

In the after-action report on the failed RFC, 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.

However, with the advent of PHP 8.1 and readonly 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.

Sapien makes extensive use of readonly, presenting a Request 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 Request than in the C versions, such as:

  • Content, built up from various content-related headers and the request body itself

  • Upload, including the new full_path value from $_FILES entries.

  • Url, computed from the various $_SERVER values

  • Accept value object collections for Type, Charset, Encoding, and Language

  • XForwarded, distilled from the various x-forwarded-* headers

  • Forwarded value object collections derived from the Forwarded header

  • Authorization\Scheme value objects for basic, bearer, and digest authorization

The Response is fundamentally the same as it was in ext-request v1, though the custom file- and JSON-specific response logic has been extracted to specialized classes. Even so, the generic response is capable of handling all sorts of content, including iterables and resources.

So, if you're starting a new PHP 8.1 project, or refactoring a legacy system to PHP 8.1, try out Sapien, because request and response objects make life so much easier.

Are you stuck with a legacy PHP application? You should buy my book because it gives you a step-by-step guide to improving you codebase, all while keeping it running the whole time.