PHPackages                             diego-ninja/granite - 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. diego-ninja/granite

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

diego-ninja/granite
===================

A lightweight zero-dependency PHP library for building immutable, serializable objects with validation capabilities.

v1.6.0(2mo ago)5996811MITPHPPHP ^8.3|^8.4CI passing

Since May 22Pushed 2mo ago3 watchersCompare

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

READMEChangelog (10)Dependencies (8)Versions (27)Used By (1)

🪨 Granite
=========

[](#-granite)

[![Latest Version on Packagist](https://camo.githubusercontent.com/05bf03dbd840471d0ce7dcfa44c1db2dbe2f33618b999f1a3e006b87eb7b7dd9/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f646965676f2d6e696e6a612f6772616e6974652e7376673f7374796c653d666c61742d73717561726526636f6c6f723d626c7565266c6f676f436f6c6f723d253233393439636134266c6162656c436f6c6f723d253233336634373530)](https://packagist.org/packages/diego-ninja/granite)[![Total Downloads](https://camo.githubusercontent.com/2c6e9298bf5a07ed82a0cfb78cb47fa65cfb99f7a62297afb651631730353c70/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f646965676f2d6e696e6a612f6772616e6974652e7376673f7374796c653d666c61742d73717561726526636f6c6f723d626c7565266c6f676f436f6c6f723d253233393439636134266c6162656c436f6c6f723d253233336634373530)](https://packagist.org/packages/diego-ninja/granite)[![PHP Version](https://camo.githubusercontent.com/746dba9cf9f5aeade240214fb41c3bf06dd7e7bed21ec8103edecde8d63071aa/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f646965676f2d6e696e6a612f6772616e6974652e7376673f7374796c653d666c61742d73717561726526636f6c6f723d626c7565266c6f676f436f6c6f723d253233393439636134266c6162656c436f6c6f723d253233336634373530)](https://camo.githubusercontent.com/746dba9cf9f5aeade240214fb41c3bf06dd7e7bed21ec8103edecde8d63071aa/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f646965676f2d6e696e6a612f6772616e6974652e7376673f7374796c653d666c61742d73717561726526636f6c6f723d626c7565266c6f676f436f6c6f723d253233393439636134266c6162656c436f6c6f723d253233336634373530)[![License: MIT](https://camo.githubusercontent.com/a26a213b909339a4120989779b78a923195a74e3915f6e0f0c619bd9f3d23208/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d626c75652e7376673f7374796c653d666c61742d73717561726526636f6c6f723d626c7565266c6f676f436f6c6f723d253233393439636134266c6162656c436f6c6f723d253233336634373530)](https://opensource.org/licenses/MIT)[![GitHub last commit](https://camo.githubusercontent.com/44463060e7da3ebb06b8e1fdef7a5ef9c62d7ce87bb1d9774d9e37a8a0c26e17/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6173742d636f6d6d69742f646965676f2d6e696e6a612f6772616e6974653f7374796c653d666c61742d73717561726526636f6c6f723d626c7565266c6f676f436f6c6f723d253233393439636134266c6162656c436f6c6f723d253233336634373530)](https://camo.githubusercontent.com/44463060e7da3ebb06b8e1fdef7a5ef9c62d7ce87bb1d9774d9e37a8a0c26e17/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6173742d636f6d6d69742f646965676f2d6e696e6a612f6772616e6974653f7374796c653d666c61742d73717561726526636f6c6f723d626c7565266c6f676f436f6c6f723d253233393439636134266c6162656c436f6c6f723d253233336634373530)[![wakatime](https://camo.githubusercontent.com/e4d23548918db20baf81085fbbd64e1c042a8f724b09ab8d43c809aedb0f9474/68747470733a2f2f77616b6174696d652e636f6d2f62616467652f757365722f62643635663035352d633966332d346637332d393261612d3363393831306637306363332f70726f6a6563742f33636332656336302d613862342d346464632d616561632d6561373865333761303934622e7376673f7374796c653d666c61742d73717561726526636f6c6f723d626c7565266c6f676f436f6c6f723d253233393439636134266c6162656c436f6c6f723d253233336634373530)](https://wakatime.com/badge/user/bd65f055-c9f3-4f73-92aa-3c9810f70cc3/project/3cc2ec60-a8b4-4ddc-aeac-ea78e37a094b)

![Tests](https://camo.githubusercontent.com/996655856780ff3e47882993929b24dff84254b7d2e6cacd54d61204def9e120/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f646965676f2d6e696e6a612f6772616e6974652f74657374732e796d6c3f6272616e63683d6d61696e267374796c653d666c61742d737175617265266c6f676f3d676974687562266c6162656c3d7465737473266c6f676f436f6c6f723d253233393439636134266c6162656c436f6c6f723d253233336634373530)![Static Analysis](https://camo.githubusercontent.com/44e56a577c1a879ab7c6a671bf0f1ccd6acfb9f3b5d1f495d58e27dd98e5e441/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f646965676f2d6e696e6a612f6772616e6974652f7374617469632d616e616c797369732e796d6c3f6272616e63683d6d61696e267374796c653d666c61742d737175617265266c6f676f3d676974687562266c6162656c3d7068707374616e2532303130266c6f676f436f6c6f723d253233393439636134266c6162656c436f6c6f723d253233336634373530)![Code Style](https://camo.githubusercontent.com/e813a87b7bb63e58580e3716a86fd7cb230e97e3373a5e108e5d8aa276ce67d2/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f646965676f2d6e696e6a612f6772616e6974652f636f64652d7374796c652e796d6c3f6272616e63683d6d61696e267374796c653d666c61742d737175617265266c6f676f3d676974687562266c6162656c3d70696e74253341253230504552266c6f676f436f6c6f723d253233393439636134266c6162656c436f6c6f723d253233336634373530)![Coveralls](https://camo.githubusercontent.com/c332c0577fc055285d8af50dbf11a47fe73bd818049a6ce05ad0bda84f27c43e/68747470733a2f2f696d672e736869656c64732e696f2f636f766572616c6c73436f7665726167652f6769746875622f646965676f2d6e696e6a612f6772616e6974653f6272616e63683d6d61696e267374796c653d666c61742d737175617265266c6f676f3d636f766572616c6c73266c6f676f436f6c6f723d253233393439636134266c6162656c436f6c6f723d253233336634373530266c696e6b3d6874747073253341253246253246636f766572616c6c732e696f253246676974687562253246646965676f2d6e696e6a612532466772616e697465)

A powerful, zero-dependency PHP library for building **immutable**, **serializable** objects with **validation** and **mapping** capabilities. Perfect for DTOs, Value Objects, API responses, and domain modeling.

🪶 Pebble - Lightweight Immutable Snapshots
------------------------------------------

[](#-pebble---lightweight-immutable-snapshots)

**Pebble** is a lightweight alternative to Granite for when you need immutable snapshots without validation overhead — ideal for caching, Eloquent snapshots, and fast comparisons.

```
$snapshot = Pebble::from($eloquentModel);

$snapshot->name;           // Magic __get
$snapshot['email'];        // ArrayAccess
$snapshot->equals($other); // O(1) fingerprint comparison
```

📖 **[Read Pebble Documentation](docs/pebble.md)**

---

✨ Features
----------

[](#-features)

- **Immutable Objects** — Read-only DTOs and Value Objects, thread-safe by design
- **Flexible `from()` Method** — Create from arrays, JSON, named parameters, other Granite objects, or mix them
- **Comprehensive Validation** — 30+ built-in rules including Carbon date validation (Age, Future, Past, BusinessDay...)
- **ObjectMapper** — Convention-based property mapping between objects with custom transformations
- **Smart Serialization** — Custom property names, naming conventions, hidden fields, Carbon date formats
- **Object Comparison** — Deep equality with `equals()`, detailed diffs with `differs()`
- **Performance Optimized** — Fast path for simple DTOs (~3.5x vs plain PHP), WeakMap caching, direct property access

🚀 Quick Start
-------------

[](#-quick-start)

### Installation

[](#installation)

```
composer require diego-ninja/granite
```

### Basic Usage

[](#basic-usage)

```
use Ninja\Granite\Granite;
use Ninja\Granite\Validation\Attributes\Required;
use Ninja\Granite\Validation\Attributes\Email;
use Ninja\Granite\Validation\Attributes\Min;
use Ninja\Granite\Serialization\Attributes\Hidden;

final readonly class User extends Granite
{
    public function __construct(
        #[Required]
        #[Min(2)]
        public string $name,

        #[Required]
        #[Email]
        public string $email,

        #[Hidden]
        public ?string $password = null,
    ) {}
}

// Create from array
$user = User::from(['name' => 'John Doe', 'email' => 'john@example.com', 'password' => 'secret']);

// Create from named parameters
$user = User::from(name: 'John Doe', email: 'john@example.com');

// Immutable updates
$updated = $user->with(['name' => 'Jane Doe']);

// Serialization (password hidden automatically)
$json = $user->json();   // {"name":"John Doe","email":"john@example.com"}
$array = $user->array();
```

📖 Documentation
---------------

[](#-documentation)

### Core Concepts

[](#core-concepts)

- **[Enhanced from() Method](docs/hydration.md)** — Multiple invocation patterns for flexible object creation
- **[Validation](docs/validation.md)** — Comprehensive validation system with 30+ built-in rules including Carbon
- **[Serialization](docs/serialization.md)** — Control how objects are converted to/from arrays and JSON with Carbon support
- **[Object Comparison](docs/comparison.md)** — Deep equality checks and difference detection
- **[ObjectMapper](docs/automapper.md)** — Powerful object-to-object mapping with conventions
- **[Pebble](docs/pebble.md)** — Lightweight immutable snapshots with fingerprinting
- **[Advanced Usage](docs/advanced_usage.md)** — Patterns for complex applications
- **[API Reference](docs/api_reference.md)** — Complete API documentation

### Guides

[](#guides)

- **[Migration Guide](docs/migration_guide.md)** — Migrate from arrays, stdClass, Doctrine, Laravel
- **[Troubleshooting](docs/troubleshooting.md)** — Common issues and solutions

📈 Performance &amp; Benchmarks
------------------------------

[](#-performance--benchmarks)

Granite uses a **multi-layer fast path** system that detects simple DTOs at class-load time and bypasses the full hydration pipeline (reflection, metadata, type conversion) entirely. For objects that qualify, the overhead vs plain PHP constructors is minimal.

### Benchmark Results

[](#benchmark-results)

Benchmarked on PHP 8.4, comparing Granite against plain PHP constructors and `Pebble` (Granite's lightweight companion). The test DTO has 6 fields (`int`, `string`, `string`, `int`, `string`, `bool`).

#### Object Creation

[](#object-creation)

Benchmarkµs/opvs Plain PHPPlain PHP constructor0.33—`Granite::from(array)`1.143.5x`Granite::from(named args)`1.133.4x`Pebble::from(array)`3.6211.1x#### Nested Object Creation (3 objects)

[](#nested-object-creation-3-objects)

Benchmarkµs/opvs Plain PHPPlain PHP constructors0.78—`Granite::from(array)`3.634.6x`Pebble::from(array)`6.808.7xGranite recursively applies the fast path to nested Granite-typed properties, so the overhead scales linearly with object depth rather than exploding through the full hydration pipeline.

#### Serialization

[](#serialization)

Benchmarkµs/opvs Plain PHPPlain PHP `toArray()`0.19—`Granite array()`0.251.3xPlain PHP `json_encode(array)`0.25—`Granite json()`0.261.0xBoth `array()` and `json()` results are cached in a `WeakMap`. Since Granite objects are readonly, the serialized representation never changes, so repeated calls return instantly. The `json()` method effectively matches native `json_encode` performance.

#### Equality Check

[](#equality-check)

Benchmarkµs/opvs Plain PHPPlain array `===`0.12—`Granite equals()`0.484.0x`Pebble equals()` (fingerprint)0.312.6xFor simple DTOs, `equals()` compares properties directly without building intermediate arrays, with early exit on the first difference.

#### Collection (100 items, create from array)

[](#collection-100-items-create-from-array)

Benchmarkµs/opvs Plain PHPPlain PHP `array_map` + constructors31—Granite `array_map` + `from()`1063.4xPebble `array_map` + `from()`34311.1x#### Property Access

[](#property-access)

Granite uses native PHP readonly promoted properties — property access is **identical** to plain PHP objects, with zero overhead:

Benchmarkµs/opPlain PHP readonly0.15Granite readonly0.14Pebble `__get()`1.03### How it works

[](#how-it-works)

Granite's performance comes from three layers of optimization:

1. **Fast path detection** (`ClassProfile`) — At class-load time, Granite analyzes each class and determines if it can skip the full hydration pipeline. A class qualifies when all constructor parameters are either primitive types (`int`, `string`, `float`, `bool`, `array`) or other Granite subclasses, and the class has no special attributes (`#[Hidden]`, `#[SerializedName]`, validation rules, etc.).
2. **WeakMap caching** — `array()` and `json()` results are cached in a `WeakMap` keyed by object instance. Since Granite objects are readonly, the cache is always valid. When the object is garbage collected, the cache entry is automatically cleaned up.
3. **Direct property access** — For serialization and comparison, Granite reads properties directly by name (`$instance->$name`) instead of going through reflection, metadata lookups, and type conversion.

Classes that don't qualify for the fast path (those with validation attributes, naming conventions, Carbon dates, etc.) use the standard hydration pipeline, which is still optimized with reflection caching and O(1) hidden property lookups.

### Running the Benchmarks

[](#running-the-benchmarks)

```
php benchmarks/GraniteBench.php
```

⚠️ Deprecation Notice
---------------------

[](#️-deprecation-notice)

`GraniteDTO` and `GraniteVO` are deprecated since v2.0.0 in favor of the unified `Granite` base class. Both still extend `Granite` for backward compatibility but will be removed in v3.0.0.

```
// ❌ Deprecated — use Granite instead
final readonly class User extends GraniteVO { }
// ✅
final readonly class User extends Granite { }
```

🔧 Requirements
--------------

[](#-requirements)

- **PHP 8.3+** — Takes advantage of modern PHP features
- **No dependencies** — Zero external dependencies for maximum compatibility

📦 Installation
--------------

[](#-installation)

```
composer require diego-ninja/granite
```

🤝 Contributing
--------------

[](#-contributing)

Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details.

📄 License
---------

[](#-license)

This package is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).

🙏 Credits
---------

[](#-credits)

This project is developed and maintained by 🥷 [Diego Rin](https://diego.ninja) in his free time.

If you find this project useful, please consider:

- ⭐ Starring the repository
- 🐛 Reporting bugs and issues
- 💡 Suggesting new features
- 🔧 Contributing code improvements

---

**Made with ❤️ for the PHP community**

###  Health Score

50

—

FairBetter than 95% of packages

Maintenance86

Actively maintained with recent releases

Popularity25

Limited adoption so far

Community14

Small or concentrated contributor base

Maturity64

Established project with proven stability

 Bus Factor1

Top contributor holds 96.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 ~19 days

Recently: every ~34 days

Total

16

Last Release

68d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/dff5b0a76de3d555cb236c400384058ba23982bce2e859cc1b2f0c1f0161a3e6?d=identicon)[diego.ninja](/maintainers/diego.ninja)

---

Top Contributors

[![diego-ninja](https://avatars.githubusercontent.com/u/78662279?v=4)](https://github.com/diego-ninja "diego-ninja (90 commits)")[![CristianPeter](https://avatars.githubusercontent.com/u/102976077?v=4)](https://github.com/CristianPeter "CristianPeter (3 commits)")

---

Tags

phpValue Objectserializabledata-transfer-objectdata mapperdtoimmutableobjectsdata structuredata objectauto-mappingauto-mapper

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan, Rector

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/diego-ninja-granite/health.svg)

```
[![Health](https://phpackages.com/badges/diego-ninja-granite/health.svg)](https://phpackages.com/packages/diego-ninja-granite)
```

###  Alternatives

[fab2s/dt0

Immutable DTOs with bidirectional casting. No framework required. 8x faster than the alternative.

101.6k1](/packages/fab2s-dt0)

PHPackages © 2026

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