PHPackages                             eddiriarte/oh - 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. eddiriarte/oh

ActiveProject

eddiriarte/oh
=============

Another simple yet neat object hydrator library for PHP.

1.0.0(4y ago)04MITPHPPHP ^8.1

Since Apr 10Pushed 4y ago1 watchersCompare

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

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

[![OH Logo](./docs/oh-logo.svg)](./docs/oh-logo.svg)

OH
==

[](#oh)

Another simple yet neat object hydrator library for PHP.

Install
-------

[](#install)

```
composer require eddiriarte/oh

```

Usage
-----

[](#usage)

This library allows conversion of data from (nested) array format into proper PHP objects.

```
// Define your class(es):
class Person
{
    public function __construct(
        private string $firstName,
        private string $lastName
    ) {}

    //... here you might define getters/setters
}

// Initialize hydrator manager:
$manager = new \EddIriarte\Oh\Manager();

// Execute hydration:
$person = $manager->hydrate(Person::class, ['first_name' => 'Bruce', 'last_name' => 'Wayne']);

assert($person instanceof Person);
```

### Array-Key Cases

[](#array-key-cases)

The default behaviour is to map snake-case keys from array into the class property/parameter names. However, whenever required its possible to configure that behaviour in the manager:

```
use EddIriarte\Oh\Manager;

$snakeCaseManager = new Manager(['source_naming_case' => StringCase::SnakeCase]); // default behaviour
$person1 = $snakeCaseManager->hydrate(Person::class, ['first_name' => 'Bruce', 'last_name' => 'Wayne']);

$camelCaseManager = new Manager(['source_naming_case' => StringCase::CamelCase]);
$person2 = $camelCaseManager->hydrate(Person::class, ['firstName' => 'Bruce', 'lastName' => 'Wayne']);

$studlyCaseManager = new Manager(['source_naming_case' => StringCase::StudlyCase]);
$person3 = $studlyCaseManager->hydrate(Person::class, ['FirstName' => 'Bruce', 'LastName' => 'Wayne']);

$kebabCaseManager = new Manager(['source_naming_case' => StringCase::KebabCase]);
$person4 = $kebabCaseManager->hydrate(Person::class, ['first-name' => 'Bruce', 'last-name' => 'Wayne']);

$anyCaseManager = new Manager(['source_naming_case' => StringCase::AnyCase]);
$person5 = $anyCaseManager->hydrate(Person::class, ['firstName' => 'Bruce', 'last_name' => 'Wayne']);
```

### Data Structure Objects

[](#data-structure-objects)

If for some reason your classes do not provide a respective constructor method, then the hydrator will try to populate matching class properties.

```
// Define your class(es):
class Person
{
    private string $firstName;
    private string $lastName;

    //... here you might define getters/setters
}

// Initialize hydrator manager:
$manager = new \EddIriarte\Oh\Manager();

// Execute hydration:
$person = $manager->hydrate(Person::class, ['first_name' => 'Bruce', 'last_name' => 'Wayne']);

assert($person instanceof Person);
```

Additionally, the manager allows to specify the visibility of properties to consider:

```
use EddIriarte\Oh\Manager;
use EddIriarte\Oh\Enums\PropertyVisibility;

class ReadOnlyPerson
{
    public readonly string $firstName;
    public readonly string $lastName;
    public int $age;
}

// Initialize hydrator manager:
$manager = new Manager(['property_visibility' => PropertyVisibility::ReadOnly]);

// Execute hydration:
$person = $manager->hydrate(ReadOnlyPerson::class, ['first_name' => 'Bruce', 'last_name' => 'Wayne', 'age' => 44]);

var_dump($person);

// class ReadOnlyPerson#700 (3) {
//   public readonly string $firstName =>
//   string(5) "Bruce"
//   public readonly string $lastName =>
//   string(5) "Wayne"
//   public int $age =>
//   *uninitialized*
// }
```

### Nested Objects

[](#nested-objects)

The hydrator loops over all properties/parameters and tries to initialize also nested types:

```
use EddIriarte\Oh\Manager;
use EddIriarte\Oh\Enums\PropertyVisibility;

class Person
{
    public function __construct(
        private string $firstName,
        private string $lastName
    ) {}
}

class Hero
{
    public function __construct(
        private string $name,
        private Person $alias
    ) {}
}

// Execute hydration:
$hero = (new Manager())->hydrate(
    Hero::class,
    [
        'name' => 'Batman',
        'alias' => [
            'first_name' => 'Bruce',
            'last_name' => 'Wayne',
        ],
    ]
);
```

### List, Dictionaries, Arrays

[](#list-dictionaries-arrays)

The hydrator already supports the population of object lists. In order to hydrate nested items into specific classes, it requires additional information, that can be provided wit PHP Attributes.

```
use EddIriarte\Oh\Attributes\ListMemberType;
use EddIriarte\Oh\Enums\PropertyVisibility;
use EddIriarte\Oh\Manager;

class Hero
{
    public function __construct(private string $name)
    {}
}

class HeroTeam
{
    public function __construct(
        private string $name,
        #[ListMemberType(Hero::class)]
        private array $heroes
    ) {}
}

$team = (new Manager())->hydrate(
    HeroTeam::class,
    [
        'name' => 'Batman & Robin',
        'heroes' => [
            ['name' => 'Batman'],
            ['name' => 'Robin'],
        ],
    ]
);
```

The usage of instantiable Arrayable classes instead of arrays is also allowed. In this example we use Doctrine's `ArrayCollection`, but could also be done with Laravel collections:

```
use Doctrine\Common\Collections\ArrayCollection;

use EddIriarte\Oh\Attributes\ListMemberType;
use EddIriarte\Oh\Enums\PropertyVisibility;
use EddIriarte\Oh\Manager;

class Hero
{
    public function __construct(private string $name)
    {}
}

class HeroTeam
{
    public function __construct(
        private string $name,
        #[ListMemberType(Hero::class)]
        private ArrayCollection $heroes
    ) {}
}

$team = (new Manager())->hydrate(
    HeroTeam::class,
    [
        'name' => 'Batman & Robin',
        'heroes' => [
            ['name' => 'Batman'],
            ['name' => 'Robin'],
        ],
    ]
);
```

Configuration
-------------

[](#configuration)

Still in progress...

NameTypeDescriptionsource\_naming\_case`StringCase` (Enum)The case of the keys used in the source array, needed to map them into the specific class property/parameter.

Default value: `StringCase::SnakeCase`property\_visibility`PropertyVisibility` (Enum)The property visibility on structure classes(without constructor) to filter fields.

Default value: `PropertyVisibility::Private`Credits
-------

[](#credits)

String case functions were copied from Laravel.

Disclaimer
----------

[](#disclaimer)

This library is still under active development and usage may change in order to optimize performance, add caching and dehydration.

###  Health Score

24

—

LowBetter than 32% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity3

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity57

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

Unknown

Total

1

Last Release

1495d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/49e7b795aef3a4403b3f45f8d878f9b283cdebcbc729a883bcdec3ed374e74cc?d=identicon)[eddiriarte](/maintainers/eddiriarte)

---

Top Contributors

[![eddiriarte](https://avatars.githubusercontent.com/u/6428870?v=4)](https://github.com/eddiriarte "eddiriarte (9 commits)")

###  Code Quality

TestsPHPUnit

Code StylePHP CS Fixer

### Embed Badge

![Health badge](/badges/eddiriarte-oh/health.svg)

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

PHPackages © 2026

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