PHPackages                             grifart/not-serializable - 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. grifart/not-serializable

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

grifart/not-serializable
========================

State explicitly that class has not been meant for serialization.

00PHP

Since Mar 30Pushed 4y ago2 watchersCompare

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

READMEChangelogDependenciesVersions (1)Used By (0)

Classes should not be serializable by default!
==============================================

[](#classes-should-not-be-serializable-by-default)

...and this package makes it easier for you.

A story
=======

[](#a-story)

In 3/2022 this has happened.

```
class UserId {
   private int $id;
   public function __construct(int $id) {$this->id = $id}
}

// later in an app
$userId = new UserId(42);
// ...
$_SESSION['user_id'] = $userId;
```

This will work. No warning, no errors, no problems. For now...

...

After a year you have decided to do internal change of `UserId` object – rename private property `$id` to `$identifier`.

```
class UserId {
-   private int $id;
+   private int $identifier;
    public function __construct(int $id) {
-        $this->id = $id
+        $this->identifier = $id
    }
}
```

There is no public change of behaviour. There is no way outer observer should be able to find any changes in object behaviour. Static analysis passes, tests passes. All good! You deploy your application.

Boom! 🔥 Application hard crashed for every user that has been logged-in on *session deserialization*. That is because implicit serialization made public interface from a private property.

### Summary

[](#summary)

Implicit serialization support is [an explosive mine 💥](https://en.wikipedia.org/wiki/Explosive_mine), that you cannot easily spot from the surface or even in code-review. You have to inspect whole object life-cycle including code history. Almost impossible to spot.

This is very similar to disabling inheritance support from object which was not explicitly designed to be extended – `final` by default. You can find good reasoning at [1](https://matthiasnoback.nl/2018/09/final-classes-by-default-why/), [2](http://whiley.org/2011/12/06/final-should-be-default-for-classes-in-java/).

**TL;DR:** You get much better object encapsulation, you know exactly how you object behaves.

The solution
============

[](#the-solution)

> 👉 **Replace implicit serialization with the explicit one.**

1. Disabling implicit serialization
-----------------------------------

[](#1-disabling-implicit-serialization)

In PHP every object is serializable by default, until you say otherwise. So let's say otherwise.

This makes most sense for *value objects* and all its derivatives like *entities*. There is however no harm by disabling serialization support for all classes as you would never-ever want to serialize a service.

Open you PhpStorm settings and then `Editor > File and Code Templates > Files > PHP Class` and update the template.

```
final class ${NAME} {
	use \Grifart\NotSerializable\NoSerialization;
}
```

[![PhpStorm default template settings](docs/phpstorm-settings.png)](docs/phpstorm-settings.png)

Require this package using composer in your project

```
composer require grifart/not-serializable
```

It contains a [simple trait](src), that disables serialization support for *PHP &gt;7.4*. That is because serialization API has been changed [php-watch](https://php.watch/versions/8.1/serializable-deprecated).

2. Making the serialization explicit
------------------------------------

[](#2-making-the-serialization-explicit)

When you **need** serialization support, implement serialization API explicitly.

Great thing is that when it is not possible to serialize by default, someone has to make a decision that **we need it be serializable**.

This allows us also choose right type of serialization:

### a) Short term &amp; simple

[](#a-short-term--simple)

PHP serialization API: Allows you to quick start. Breaks when you start moving your classes around (heavily depends on our classes FQNs).

You can go this way by:

1. removing the trait
2. implementing `__serialize()` and `__unserialize()` methods.

### b) Long term serialization

[](#b-long-term-serialization)

[grifart/stateful](https://github.com/grifart/stateful): Provides strict versioning, field checking and FQN routing. Designed for:

- serialization that can be deserialized after years (e.g. immutable event streams)
- situation when codebase changes significantly
- for maximal strictness, so it fails on you dev machine, not on production.

You can go this way by:

1. removing the trait
2. implementing `Stateful` interface &amp; `composer require `[grifart/stateful](https://github.com/grifart/stateful)

Further development
===================

[](#further-development)

- PhpStan / Rector rule, that finds/fixes classes that does not have serialization disables and does NOT implement serialization explicitly (How to apply this only to value objects &amp; derivatives?)

###  Health Score

14

—

LowBetter than 2% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity0

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity26

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% 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.

### Community

Maintainers

![](https://www.gravatar.com/avatar/939d12e9a77e30f843e33a785f81d8ee45b71bf2db88c0d32c0d36571c71a58d?d=identicon)[jkuchar](/maintainers/jkuchar)

---

Top Contributors

[![jkuchar](https://avatars.githubusercontent.com/u/133822?v=4)](https://github.com/jkuchar "jkuchar (14 commits)")

### Embed Badge

![Health badge](/badges/grifart-not-serializable/health.svg)

```
[![Health](https://phpackages.com/badges/grifart-not-serializable/health.svg)](https://phpackages.com/packages/grifart-not-serializable)
```

PHPackages © 2026

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