PHPackages                             mikespub/micheh-psr7-cache - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [HTTP &amp; Networking](/categories/http)
4. /
5. mikespub/micheh-psr7-cache

ActiveLibrary[HTTP &amp; Networking](/categories/http)

mikespub/micheh-psr7-cache
==========================

Cache and conditional request helpers for PSR-7 HTTP Messages

2.0.4(3mo ago)08372BSD-3-ClausePHPPHP &gt;=8.1CI passing

Since Aug 15Pushed 3mo agoCompare

[ Source](https://github.com/mikespub-org/micheh-psr7-cache)[ Packagist](https://packagist.org/packages/mikespub/micheh-psr7-cache)[ RSS](/packages/mikespub-micheh-psr7-cache/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (1)Dependencies (3)Versions (12)Used By (2)

Cache helpers for PSR-7 HTTP Messages
=====================================

[](#cache-helpers-for-psr-7-http-messages)

[![Latest Version on Packagist](https://camo.githubusercontent.com/865f299aa030b9194b4b73ebc92a60c1c4273a6f3e3d68ffa147117291639ac4/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6d696b65737075622f6d69636865682d707372372d63616368652e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/mikespub/micheh-psr7-cache)[![Software License](https://camo.githubusercontent.com/4cd8f37b78f099bae3b2c34e726f546fe212b58a66131ffd084b78f9802ab04e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4253445f332d2d436c617573652d627269676874677265656e2e7376673f7374796c653d666c61742d737175617265)](LICENSE)[![Testing](https://github.com/mikespub-org/micheh-psr7-cache/workflows/testing/badge.svg)](https://github.com/mikespub-org/micheh-psr7-cache/workflows/testing/badge.svg)[![Total Downloads](https://camo.githubusercontent.com/8fa82619143a54b2dd56ce7b6a87da81113b3098253a196fe461371f9cd6e2de/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6d696b65737075622f6d69636865682d707372372d63616368652e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/mikespub/micheh-psr7-cache)

This library provides an easy way to either add cache relevant headers to a PSR-7 HTTP message implementation, or to extract cache and conditional request information from a PSR-7 message (e.g. if a response is cacheable). It also provides a `Cache-Control` value object to provide an object oriented interface for the manipulation of the `Cache-Control` header.

Installation of this fork (PHP 8.1+)
------------------------------------

[](#installation-of-this-fork-php-81)

Install this library using [Composer](https://getcomposer.org/):

```
$ composer require mikespub/micheh-psr7-cache
```

Note: the original package is still available at [micheh/psr7-cache](https://packagist.org/packages/micheh/psr7-cache) but it is no longer maintained

Quickstart
----------

[](#quickstart)

To enable caching of HTTP responses, create an instance of `CacheUtil`, call the method `withCache` and provide your PSR-7 response.

```
/** @var \Psr\Http\Message\ResponseInterface $response */

$util = new \Micheh\Cache\CacheUtil();
$response = $util->withCache($response);
```

This will add the header `Cache-Control: private, max-age=600` to your response. With this header the response will only be cached by the client who sent the request and will be cached for 600 seconds (10 min). During this time the client should use the response from the cache and should not make a new request to the application.

### Cache Validators

[](#cache-validators)

The application should also add Cache Validators to the response: An `ETag` header (and `Last-Modified` header if you know when the resource was last modified). This way the client will also include the `ETag` and `Last-Modified` information in the request and the application can check if the client still has the current state.

```
/** @var \Psr\Http\Message\ResponseInterface $response */

$util = new \Micheh\Cache\CacheUtil();
$response = $util->withCache($response);
$response = $util->withETag($response, 'my-etag');
$response = $util->withLastModified($response, new \DateTime());
```

### Revalidate a response

[](#revalidate-a-response)

To determine if the client still has a current copy of the page and the response is not modified, you can use the `isNotModified` method. Simply add the cache headers to the response and then call the method with both the request and the response. The method will automatically compare the `If-None-Match` header of the request with the `ETag` header of the response (and/or the `If-Modified-Since` header of the request with the `Last-Modified` header of the response if available). If the response is not modified, return the empty response with the cache headers and a status code `304` (Not Modified). This will instruct the client to use the cached copy from the previous request, saving you CPU/memory usage and bandwidth. Therefore it is important to keep the code before the `isNotModified` call as lightweight as possible to increase performance. Don't create the complete response before this method.

```
/** @var \Psr\Http\Message\RequestInterface $request */
/** @var \Psr\Http\Message\ResponseInterface $response */

$util = new \Micheh\Cache\CacheUtil();
$response = $util->withCache($response);
$response = $util->withETag($response, 'my-etag');
$response = $util->withLastModified($response, new \DateTime());

if ($util->isNotModified($request, $response)) {
    return $response->withStatus(304);
}

// create the body of the response
```

### Conditional request with unsafe method

[](#conditional-request-with-unsafe-method)

While the procedure described above is usually optional and for safe methods (GET and HEAD), it is also possible to enforce that the client has the current resource state. This is useful for unsafe methods (e.g. POST, PUT, PATCH or DELETE), because it can prevent lost updates (e.g. if another client updates the resource before your request). It is a good idea to initially check if the request includes the appropriate headers (`If-Match` for an `ETag` and/or `If-Unmodified-Since` for a `Last-Modified` date) with the `hasStateValidator` method. If the request does not include this information, abort the execution and return status code `428` (Precondition Required) or status code `403` (Forbidden) if you only want to use the original status codes.

```
/** @var \Psr\Http\Message\RequestInterface $request */

$util = new \Micheh\Cache\CacheUtil();
if (!$util->hasStateValidator($request)) {
    return $response->withStatus(428);
}
```

If the state validators are included in the request, you can check if the request has the current resource state and not an outdated version with the method `hasCurrentState`. If the request has an outdated resource state (another `ETag` or an older `Last-Modified` date), abort the execution and return status code `412` (Precondition Failed). Otherwise you can continue to process the request and update/delete the resource. Once the resource is updated, it is a good idea to include the updated `ETag` (and `Last-Modified` date if available) in the response.

```
/** @var \Psr\Http\Message\RequestInterface $request */
/** @var \Psr\Http\Message\ResponseInterface $response */

$util = new \Micheh\Cache\CacheUtil();
if (!$util->hasStateValidator($request)) {
    return $response->withStatus(428);
}

$eTag = 'my-etag'
$lastModified = new \DateTime();
if (!$util->hasCurrentState($request, $eTag, $lastModified)) {
    return $response->withStatus(412);
}

// process the request
```

Available helper methods
------------------------

[](#available-helper-methods)

MethodDescription (see the phpDoc for more information)`withCache`Convenience method to add a `Cache-Control` header, which allows caching`withCachePrevention`Convenience method to prevent caching`withExpires`Adds an `Expires` header from a timestamp, string or DateTime`withRelativeExpires`Adds an `Expires` header with a specific lifetime`withETag`Adds an `ETag` header`withLastModified`Adds a `Last-Modified` header from a timestamp, string or DateTime`withCacheControl`Adds a `Cache-Control` header from a string or value object`hasStateValidator`Checks if it is possible to determine the resource state`hasCurrentState`Checks if a request has the current resource state`isNotModified`Checks if a response is not modified`isCacheable`Checks if a response is cacheable by a public cache`isFresh`Checks if a response is fresh (age smaller than lifetime)`getLifetime`Returns the lifetime of a response (how long it should be cached)`getAge`Returns the age of a response (how long it was in the cache)References
----------

[](#references)

- [RFC7234: Caching](https://tools.ietf.org/html/rfc7234)
- [RFC7232: Conditional Requests](https://tools.ietf.org/html/rfc7232) (Cache Validation)
- [RFC5861: Cache-Control Extensions for Stale Content](https://tools.ietf.org/html/rfc5861)

License
-------

[](#license)

The files in this archive are licensed under the BSD-3-Clause license. You can find a copy of this license in [LICENSE.md](LICENSE.md).

###  Health Score

51

—

FairBetter than 96% of packages

Maintenance81

Actively maintained with recent releases

Popularity18

Limited adoption so far

Community12

Small or concentrated contributor base

Maturity78

Established project with proven stability

 Bus Factor1

Top contributor holds 77.8% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~424 days

Recently: every ~194 days

Total

10

Last Release

101d ago

Major Versions

0.5 → 2.0.02023-12-14

PHP version history (2 changes)0.1PHP &gt;=5.4

2.0.0PHP &gt;=8.1

### Community

Maintainers

![](https://www.gravatar.com/avatar/e9d0d3fe4bc8619159b6d18ea3fac40102ac68cb75a5a32bce661f75e47da2eb?d=identicon)[mikespub](/maintainers/mikespub)

---

Top Contributors

[![micheh](https://avatars.githubusercontent.com/u/1307920?v=4)](https://github.com/micheh "micheh (35 commits)")[![mikespub](https://avatars.githubusercontent.com/u/1447115?v=4)](https://github.com/mikespub "mikespub (10 commits)")

---

Tags

httpresponserequestpsrpsr-7http-messagecacheconditionalif-matchif-none-matchif-modified-sinceif-unmodified-since

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/mikespub-micheh-psr7-cache/health.svg)

```
[![Health](https://phpackages.com/badges/mikespub-micheh-psr7-cache/health.svg)](https://phpackages.com/packages/mikespub-micheh-psr7-cache)
```

###  Alternatives

[psr/http-message

Common interface for HTTP messages

7.1k1.0B5.5k](/packages/psr-http-message)[fig/http-message-util

Utility classes and constants for use with PSR-7 (psr/http-message)

39489.0M274](/packages/fig-http-message-util)[art4/requests-psr18-adapter

Use WordPress/Requests as a PSR-18 HTTP client

153.3k](/packages/art4-requests-psr18-adapter)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
