PHPackages                             yeast/loafpan - 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. yeast/loafpan

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

yeast/loafpan
=============

Object and config hydration from associative arrays

v0.2.0(4y ago)019MITPHP

Since Feb 2Pushed 2y ago1 watchersCompare

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

READMEChangelog (1)Dependencies (10)Versions (4)Used By (0)

Loafpan
=======

[](#loafpan)

[![QA](https://github.com/yeastphp/loafpan/actions/workflows/qa.yml/badge.svg)](https://github.com/yeastphp/loafpan/actions/workflows/qa.yml)

A simple PHP 8 native object expansion (or hydration as some call it) framework

### Features

[](#features)

- Only focused on deserialization of data, thus perfect for configs
- JSON Schema generation (also works for yaml!)
- PHP 8 Attribute guided
- Simple templating/generics support
- Simple alternative format expanders
- Custom expander support allows for expanding out-of-branch objects
- Readable code generation, for ease of debugging and speed

### Installation

[](#installation)

```
composer require yeast/loafpan
```

### Very quick use

[](#very-quick-use)

```
$config      = json_decode($json, true);

$loafpan     = new Loafpan($loafpanCacheDirectory);
// Don't forget to annotate your class.
$configClass = $loafpan->expand(MyConfig::class, $config);
```

Usage
-----

[](#usage)

To start using Loafpan, you first need to annotate your objects, in the next few examples we will create to fake classes to explain the details

An expandable object is called a "Unit", Units either need to be either annotated with `Unit` or have a custom expander registered. However for now we'll cover annotated Units

In the first example, Sandwich is a purely setter based unit, and will use the default constructor to instantiate the object and then set the properties manually.

Loafpan is here guided by the `Field` attributes, which signal which properties can be applied from an object.

```
// The first argument of `Unit` is the description of the object
// This is used in the JSON Schema generation
#[Unit("This is a very nice sandwich")]
class Sandwich {
    // A custom field name can be given with the `name` parameter
    #[Field(name: "title")]
    public string $name = "";
    // since PHP has no native support for generics or typed arrays (yet)
    // one can override the type, and use list to define the actual type
    #[Field("The toppings of this sandwich", type: 'list')]
    public array $toppings = [];
}
```

Topping however is a purely expander based, and will take only a string, as this is the only instantiation method available

Expander functions are public static functions with either 1 or 2 arguments (the optional second one being a Loafpan instance), the first argument defines the input type that can be used to expand the object from, e.g. Topping can be made from a string alone

```
#[Unit("What goes on the bread stays on the bread")]
class Topping {
    private function __construct(private bool $wet = false) {}

    #[Expander]
    public static function fromName(string $name) {
        return new static($name === 'water' ? true : false);
    }
}
```

While Topping only defines 1 Expander, you can add multiple, be aware that the results can be unpredictable when the types overlap.

With the 2 classes we just defined, a valid json object for Sandwich would be

```
{
  // because the "name" property has set it's name to "title",
  // the json object must use title
  "title": "Soggy sandwich",
  "toppings": [
    "water",
    "2 pounds of lead"
  ]
}
```

which will roughly translate into

```
$sandwich = new Sandwich();
$sandwich->name = "Soggy sandwich";
$sandwich->toppings = [
   Topping::fromString("water"),
   Topping::fromString("2 pounds of lead")
];
```

Finally, applying all this, create a Loafpan instance with a directory in which it can scribble php files and call `expand` with the class you want to expand into, in our case `Sandwich` and the user input.

The following example shows this usage

```
$loafpan = new Loafpan($yourLoafpanCacheDirectory);
/** @var Sandwich $sandwich */
$sandwich = $loafpan->expand(Sandwich::class, [
    "title" => "Soggy sandwich",
    "toppings" => [
        "water",
        "2 pounds of lead"
    ]
]);

echo "I have a sandwich called " . $sandwich->name . " the topping:\n";
foreach ($sandwich->toppping as $topping) {
    echo " - " . ($topping->wet ? 'wet' : 'not wet') . "\n";
}
```

If the options given here doesn't give you enough flexibility, you can always implement your own expander by implementing `UnitExpander` (`\Yeast\Loafpan\UnitExpander`) on a class and either registering it to loafpan by using the `registerExpander` function on a Loafpan instance or setting the `expander` parameter on the `Unit` attribute

See [src/Expander](src/Expander) for some examples of custom UnitExpanders

Default expanders
-----------------

[](#default-expanders)

- `list` - only accepts an array list with items of type T
- `map` - only accepts an associative array with items of type T
- `DateTime`/`DateTimeImmutable` - only accepts a string with an ISO-8601 formatted date
- `Ramsey\Uuid\Uuid`/`Ramsey\Uuid\UuidInterface` - only accepts a string with a properly formatted UUID

Todo
----

[](#todo)

- Generate in-depth errors about invalid input

###  Health Score

20

—

LowBetter than 14% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity6

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity41

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 ~2 days

Total

3

Last Release

1560d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/877f8b03f356ee05623fbcce6506c34a3772eaf88561adfdd508744e87d0de02?d=identicon)[eater](/maintainers/eater)

---

Top Contributors

[![the-eater](https://avatars.githubusercontent.com/u/1922630?v=4)](https://github.com/the-eater "the-eater (18 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan, Psalm

Type Coverage Yes

### Embed Badge

![Health badge](/badges/yeast-loafpan/health.svg)

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

###  Alternatives

[composer/composer

Composer helps you declare, manage and install dependencies of PHP projects. It ensures you have the right stack everywhere.

29.4k187.2M2.6k](/packages/composer-composer)[friendsofphp/php-cs-fixer

A tool to automatically fix PHP code style

13.5k234.7M20.6k](/packages/friendsofphp-php-cs-fixer)[civicrm/civicrm-core

Open source constituent relationship management for non-profits, NGOs and advocacy organizations.

728272.9k20](/packages/civicrm-civicrm-core)[ramsey/conventional-commits

A PHP library for creating and validating commit messages according to the Conventional Commits specification. Includes a CaptainHook action!

1931.2M122](/packages/ramsey-conventional-commits)[laminas/laminas-config-aggregator

Lightweight library for collecting and merging configuration from different sources

384.0M124](/packages/laminas-laminas-config-aggregator)[phootwork/lang

Missing PHP language constructs

1224.8M8](/packages/phootwork-lang)

PHPackages © 2026

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