PHPackages                             mindplay/stately - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. mindplay/stately

Abandoned → [kodus/session](/?search=kodus%2Fsession)ArchivedLibrary[Utility &amp; Helpers](/categories/utility)

mindplay/stately
================

Session abstraction for PSR-7

147PHP

Since Aug 6Pushed 10y ago1 watchersCompare

[ Source](https://github.com/mindplay-dk/stately)[ Packagist](https://packagist.org/packages/mindplay/stately)[ RSS](/packages/mindplay-stately/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependenciesVersions (1)Used By (0)

mindplay/stately
================

[](#mindplaystately)

This library implements a simple session abstraction that integrates with a [PSR-7](http://www.php-fig.org/psr/psr-7/) HTTP abstraction, to replace PHP's built-in session management.

This means you will not be using `$_SESSION` or the `session_*()` functions.

The API approach relies on type-hinted closures as a means of creating/updating session state. In practice, this means every session variable will be an object, which means your session state will really be exposed to you as a model, not as an array or a key/value store; which is great for IDE support and for code comprehension in general - for example:

```
$product_id = 123;
$amount = 4;

$session->update(function (ShoppingCart $cart) use ($product_id, $amount) {
    $cart->items[] = new CartItem($product_id, $amount);
});
```

Note that the `ShoppingCart` model is automatically created, if it isn't already present in the session data. As such, every session model is a "singleton", as far as session state goes, though not in the sense that you can't create more than one instance in a test-suite.

This is analogous to e.g. `$_SESSION['ShoppingCart'] = new ShoppingCart()`, but eliminates the unsafe use of arrays and strings, the need to test if the session variable is already set, the need to type-hint when reading from `$_SESSION`, and so on.

If you don't want to auto-create a missing model, you can type-hint the argument as e.g. `ShoppingCart $cart = null` - of course, this implies you're going to handle a missing `$cart` in your callback with an `if`-statement.

Also note, it's possible to use multiple arguments to obtain multiple session models in a single call.

You can also `remove()` session models from the current session, or `clear()` the entire contents of the container - see the [SessionContainer](src/SessionContainer.php)interface for documentation.

#### Implementation

[](#implementation)

You should create `SessionService` centrally (usually in a DI container) and expose it to consumers (usually controllers) as `SessionContainer`, which is the public portion of the interface. The internal portion of the interface includes the `commit()` method, which should be called centrally, as part of your request/response pipeline (middleware, framework or front controller), e.g. immediately after the controller has been dispatched, before you emit the response.

#### Example

[](#example)

Note that auto-creation implies that your session models must always have an empty constructor - which implies it must have no hard dependencies. Try to view this as "a good thing" - it means you won't be tempted to do things like adding a `getUser()` method for a `$user_id` property, which would imply a dependency on a `UserRepository` of some sort.

This is called "feature envy", and it's an anti-pattern - you're trying to provide a more convenient way to interact with the model, which would be great, except your model is now really a service and not just a model, even if it is internally using a repository to provide that service.

The clean approach to this problem, is a separate user service, which internally uses the session container to interact with the session model - the intention is is not for a consumer to reach into `$_SESSION` for your component's session data, just as the expectation is not that a consumer directly accesses your session model; but rather to encapsulate that exchange privately inside a service.

For example:

```
class ActiveUser
{
    /** @var int|null active user ID (or NULL, if no User is logged in) */
    public $user_id;
}

class UserService
{
    private $container;
    private $repo;

    public function __construct(SessionContainer $container, UserRepository $repo)
    {
        $this->container = $container;
        $this->repo = $repo;
    }

    /**
     * @return User
     */
    public function getUser()
    {
        $user_id = $this->container->update(function (ActiveUser $user) {
            return $user->user_id;
        });

        return $user_id
            ? $this->repo->getUserById($user_id)
            : null;
    }
}
```

The `User` model is now conveniently exposed by the `UserService`, which internally uses the `ActiveUser` model for session persistence.

###  Health Score

21

—

LowBetter than 18% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity9

Limited adoption so far

Community4

Small or concentrated contributor base

Maturity41

Maturing project, gaining track record

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.

### Community

Maintainers

![](https://www.gravatar.com/avatar/9445f567f43ee7a963270651e40e533634586f959e4df3d5398d001b1cb49be8?d=identicon)[mindplay.dk](/maintainers/mindplay.dk)

### Embed Badge

![Health badge](/badges/mindplay-stately/health.svg)

```
[![Health](https://phpackages.com/badges/mindplay-stately/health.svg)](https://phpackages.com/packages/mindplay-stately)
```

###  Alternatives

[desandro/imagesloaded

JavaScript is all like \_You images done yet or what?\_

8.9k439.0k1](/packages/desandro-imagesloaded)

PHPackages © 2026

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