PHPackages                             fasano/phprimitives - 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. fasano/phprimitives

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

fasano/phprimitives
===================

Tools for building rich domain primitives.

1.0.1(1mo ago)852MITPHPPHP ^8.4

Since Mar 10Pushed 1mo agoCompare

[ Source](https://github.com/n-fasano/phprimitives)[ Packagist](https://packagist.org/packages/fasano/phprimitives)[ RSS](/packages/fasano-phprimitives/feed)WikiDiscussions main Synced 1mo ago

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

 [![](phprimitives.png)](phprimitives.png)

 *Tools for building rich domain primitives in PHP.*

Installation
------------

[](#installation)

```
composer require fasano/phprimitives
```

What is this?
-------------

[](#what-is-this)

PHP has no base class for scalars - so there's nowhere to hook validation, enforce invariants, or express domain meaning. PHPrimitives fills that gap with 4 base classes:

- [AbstractString](/src/AbstractString.php)
- [AbstractInteger](/src/AbstractInteger.php)
- [AbstractFloat](/src/AbstractFloat.php)
- [AbstractBoolean](/src/AbstractBoolean.php)

How to use them?
----------------

[](#how-to-use-them)

Simply extend the base classes, and implement the `validate` method. Throw an `InvalidArgumentException` if the value is invalid.

```
readonly class Email extends AbstractString
{
    protected static function validate(string $value): void
    {
        if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
            throw new InvalidArgumentException('Invalid email address: ' . $value);
        }
    }
}
```

Why use them?
-------------

[](#why-use-them)

Primitives enforce invariants at the edges of your application. Validate at boundaries, trust everywhere else. Primitives convert to/from scalars at your application edges:

```
# Input boundary - scalar to primitive
$age = new Age($request->input('age'));           # Throws if invalid
$email = new Email($request->input('email'));     # Throws if invalid
```

```
# Everywhere else - work with primitives
function createUser(Email $email, Age $age): User
{
    # Type system guarantees correctness
    # No defensive checks required
}
```

```
# Output boundary - primitive to scalar
$repository->save([
    'email' => $email->value,
    'age' => $age->value,
]);
```

**Without primitives**, validation scatters throughout your codebase:

```
function createUser(string $email, int $age): void
{
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { /* ... */ }
    if ($age < 0 || 120 < $age) { /* ... */ }
    # Repeat in every function that touches these values
}
```

**Key benefits:**

- **Invariants enforced at construction** — Invalid data cannot enter your domain
- **Type safety through nominal typing** — Can't pass `Age` where `Temperature` is expected, even though both wrap integers
- **Domain concepts expressed clearly** — `Email` is more meaningful than `string`

Serialization
-------------

[](#serialization)

Primitives implement `JsonSerializable` out of the box:

```
echo json_encode(new Person(
    new Name('John'),
    new Age(18),
    new Email('john@example.com'),
));
// {"name":"John","age":18,"email":"john@example.com"}
```

Ecosystem
---------

[](#ecosystem)

The wrapping and unwrapping of values into primitive objects can be automated fairly trivially. You can find very simple libs to do so in Symfony and Doctrine below, along with a full example project that uses **no scalars anywhere**.

PackageDescription[phprimitives-doctrine](https://github.com/n-fasano/phprimitives-doctrine)Doctrine DBAL type mappings[phprimitives-symfony](https://github.com/n-fasano/phprimitives-symfony)Symfony Serializer integration[phprimitives-example](https://github.com/n-fasano/phprimitives-example)An in-context example usage of PHPrimitives

###  Health Score

43

—

FairBetter than 91% of packages

Maintenance89

Actively maintained with recent releases

Popularity11

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity52

Maturing project, gaining track record

 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.

###  Release Activity

Cadence

Every ~0 days

Total

2

Last Release

59d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/16bb6f7b889777bcd3237bbddd90a3707306fc1803da0bd10c3710086b8702a4?d=identicon)[nfasano](/maintainers/nfasano)

---

Top Contributors

[![n-fasano](https://avatars.githubusercontent.com/u/46872160?v=4)](https://github.com/n-fasano "n-fasano (8 commits)")

---

Tags

libraryphpprimitive-obsessionprimitive-typessemantic-codestrongly-typedvalue-object

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/fasano-phprimitives/health.svg)

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

PHPackages © 2026

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