PHPackages                             sdboyer/frozone - 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. sdboyer/frozone

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

sdboyer/frozone
===============

Freeze and lock objects. Also makes you 23% more like Samuel L. Jackson.

1.0.2(12y ago)5131MITPHPPHP &gt;=5.4

Since Feb 6Pushed 11y ago1 watchersCompare

[ Source](https://github.com/sdboyer/frozone)[ Packagist](https://packagist.org/packages/sdboyer/frozone)[ Docs](http://github.com/sdboyer/frozone)[ RSS](/packages/sdboyer-frozone/feed)WikiDiscussions master Synced 2mo ago

READMEChangelogDependencies (2)Versions (4)Used By (0)

Frozone
=======

[](#frozone)

[![Frozone stops writes like a boss](frozone.jpg)](frozone.jpg)[![Build Status](https://camo.githubusercontent.com/d76af45e7109a26def89c5d94313de63eeeb375366bb6be686bfda4c0915abf8/68747470733a2f2f7472617669732d63692e6f72672f7364626f7965722f66726f7a6f6e652e706e673f6272616e63683d6d6173746572)](https://travis-ci.org/sdboyer/frozone)[![Coverage Status](https://camo.githubusercontent.com/299d71512f5d748c443c290b2467d80bbc8d7f8eb3babda45d3c3c8bd8ee5ac6/68747470733a2f2f636f766572616c6c732e696f2f7265706f732f7364626f7965722f66726f7a6f6e652f62616467652e706e67)](https://coveralls.io/r/sdboyer/frozone)[![Latest Stable Version](https://camo.githubusercontent.com/272cb8909fd68f80b930bf43a0733e9670c2f2a8f5019923b4103611f725bd7e/68747470733a2f2f706f7365722e707567782e6f72672f7364626f7965722f66726f7a6f6e652f762f737461626c652e706e67)](https://packagist.org/packages/sdboyer/frozone)

Managing state sucks. Frozone is a simple set of interfaces and traits (so, PHP &gt;=5.4) that implement some patterns to make it easier. It facilitates two cases:

- **Freezing**, in which an object with mutable state is irrevocably locked such that that state cannot be further mutated (from the outside).
- **Locking** in which an object with mutable state is locked with a key, and that state cannot be mutated until the same key is provided to unlock.

Freezing
--------

[](#freezing)

Freezing is a one-way operation, initiated by calling the `freeze()` method.

```
use Frozone\Freezable;
use Frozone\FreezableTrait;

class Counter implements Freezable {
    use FreezableTrait;

    protected $callcount = 0;

    public function incrementAndEcho() {
        $this->attemptWrite();
        // or $this->attemptWriteWithMethod(__METHOD__);
        // or $this->attemptWriteWithMessage('What the exception will say if it's frozen');

        // now, your method's state-changing logic.
        echo ++$this->callcount;
    }

    public function justEcho() {
        echo $this->callcount;
    }
}

$counter = new Counter();
$counter->isFrozen(); // return FALSE
$counter->incrementAndEcho(); // prints '1'

$counter->freeze();
$counter->isFrozen(); // return TRUE

$counter->justEcho(); // prints '1'
$counter->incrementAndEcho(); // throws FrozenObjectException
```

Locking
-------

[](#locking)

Locking is a reversible operation, initiated by calling the `lock()` method with a key, and reversed by calling `unlock()` with the same key.

It is useful if you need to send a mutable object around to other code, but want to restrict mutations for as long as the object is in that context.

```
use Frozone\Lockable;
use Frozone\LockableTrait;

class Counter implements Lockable {
    use LockableTrait;

    protected $callcount = 0;

    public function incrementAndEcho() {
        $this->attemptWrite();
        // or $this->attemptWriteWithMethod(__METHOD__);
        // or $this->attemptWriteWithMessage('What the exception will say if it's frozen');

        // now, your method's state-changing logic.
        echo ++$this->callcount;
    }

    public function justEcho() {
        echo $this->callcount;
    }
}

$counter = new Counter();
$counter->isLocked(); // return FALSE
$counter->incrementAndEcho(); // prints '1'

$key = mt_rand(1, 10000); // Use a key appropriate for your use case
$counter->lock($key);
$counter->isLocked(); // return TRUE

$counter->justEcho(); // prints '1'
$counter->incrementAndEcho(); // throws LockedObjectException
$counter->unlock('foo'); // throws LockedObjectException; wrong key
$counter->lock('foo'); // throws LockedObjectException; already locked

$counter->unlock($key);
$counter->isLocked(); // return FALSE
$counter->incrementAndEcho(); // prints '2'
```

FAQ
---

[](#faq)

**Reflection can change PHP object state, regardless of visibility. Doesn't that make this pointless?**

On a purely functional level, it absolutely does.

On an API design level, even if it's possible for calling code to override the protections provided by Frozone, if your object shouldn't be mutated in a specific context/after a certain point, it's still preferable to provide clear feedback to client code that that's the contract you're providing.

**Is object state really worth managing in PHP?**

In a lot of older PHP applications, no. Being that in the vast majority of PHP applications' execution environments, state is built from scratch on each request, object state tends to have a lot less meaning. But, as more and more modern PHP applications emerge, certain types of state are being effectively encapsulated in objects. In those cases, it's worth managing.

###  Health Score

28

—

LowBetter than 54% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity11

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity60

Established project with proven stability

 Bus Factor1

Top contributor holds 91.7% 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 ~0 days

Total

3

Last Release

4475d ago

### Community

Maintainers

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

---

Top Contributors

[![sdboyer](https://avatars.githubusercontent.com/u/21599?v=4)](https://github.com/sdboyer "sdboyer (22 commits)")[![cordoval](https://avatars.githubusercontent.com/u/328359?v=4)](https://github.com/cordoval "cordoval (2 commits)")

---

Tags

phplibrarystatefrozonetheincredibles

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/sdboyer-frozone/health.svg)

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

PHPackages © 2026

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