PHPackages                             funeralzone/valueobjects - 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. funeralzone/valueobjects

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

funeralzone/valueobjects
========================

A PHP 7.1 value objects helper library.

0.5(5y ago)66643.3k↓12.7%7[2 issues](https://github.com/funeralzone/valueobjects/issues)20MITPHPPHP ^7.1 || ^8.0

Since Dec 8Pushed 5y ago5 watchersCompare

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

READMEChangelog (10)Dependencies (5)Versions (29)Used By (20)

valueobjects
============

[](#valueobjects)

[![Build Status](https://camo.githubusercontent.com/4de63f7b014a5a816bc5d346e4188722e59c49d25997d3475c934126975e5ec5/68747470733a2f2f7472617669732d63692e6f72672f66756e6572616c7a6f6e652f76616c75656f626a656374732e737667)](https://travis-ci.org/funeralzone/valueobjects)[![Version](https://camo.githubusercontent.com/9401865261fda5b8ad5b35732877286f6395c22e531fa51236b89297929bf658/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f66756e6572616c7a6f6e652f76616c75656f626a656374732e737667)](https://packagist.org/packages/funeralzone/valueobjects)

Requirements
------------

[](#requirements)

Requires PHP &gt;= 7.1

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

[](#installation)

Through Composer, obviously:

```
composer require funeralzone/valueobjects

```

Extensions
----------

[](#extensions)

This library only deals with fundamental values (scalars). We've also released an [extension library](https://github.com/funeralzone/valueobject-extensions) which provides a starting point for more complex values.

Our approach
------------

[](#our-approach)

We've written up our philosophy to PHP value objects in our [A better way of writing value objects in PHP](https://medium.com/funeralzone) article.

Single value object
-------------------

[](#single-value-object)

If your VO encapsulates a single value, it's most likely a scalar. We've provided some traits to deal with scalars under:

*src/Scalars*

Let's say you have a domain value called 'User Email'. You'd create a class which implements the `ValueObject` interface:

```
final class UserEmail implements ValueObject {
...
```

You now need to implement the interface. But because an email can essentially be considered a special kind of string (in this simple case) the `StringTrait` helper trait can implement most of the interface for you:

```
final class UserEmail implements ValueObject {

    use StringTrait;
...
```

In our case, a user's email has other domain logic that we can encapsulate in our VO. User emails have to be a valid email:

```
...
    public function __construct(string $string)
    {
        Assert::that($string)->email();
        $this->string = $string;
    }
...
```

You can see an example of how to implement single value objects in the examples directory.

Enums
-----

[](#enums)

Enums can be defined easily through use of the `EnumTrait`. Then, the enum values are simply listed as constants on the class.

```
final class Fastening implements ValueObject
{
    use EnumTrait;

    public const BUTTON = 0;
    public const CLIP = 1;
    public const PIN = 2;
    public const ZIP = 3;
}
```

When dealing with value object serialisation, the constant names are used. They are case-sensitive. So:

```
$fastening = Fastening::fromNative('BUTTON');
$fastening->toNative(); // Equals to string: 'BUTTON'
```

In code, the trait utilises magic methods to create objects based on constant name like so:

```
$fastening = Fastening::ZIP();
$fastening->toNative(); // Equals 'ZIP'
```

If your IDE supports code completion and you'd like to use named methods to create enums you can add the following PHPDoc block to your enum class:

```
/**
 * @method static Fastening BUTTON()
 * @method static Fastening CLIP()
 * @method static Fastening PIN()
 * @method static Fastening ZIP()
 */
final class Fastening implements ValueObject
```

Composite value objects
-----------------------

[](#composite-value-objects)

A composite value object is a more complex value which is made from other values.

```
final class Location implements ValueObject
{
    use CompositeTrait;

    private $latitude;
    private $longitude;

    public function __construct(Latitude $latitude, Longitude $longitude)
    {
        $this->latitude = $latitude;
        $this->longitude = $longitude;
    }

    public function getLatitude(): Latitude
    {
        return $this->latitude;
    }

    public function getLongitude(): Longitude
    {
        return $this->longitude;
    }
...
```

A `Location` is made up of two VOs (latitude, longitude). We've provided a `CompositeTrait` to easily implement most of the `ValueObject` interface automatically. It handles `toNative` serialistation by using reflection to return an array of all the class properties.

The `CompositeTrait` does not implement `fromNative`. We leave the construction of your object up to you.

```
...
    public static function fromNative($native)
    {
        return new static(
            Latitude::fromNative($native['latitude']),
            Longitude::fromNative($native['longitude'])
        );
    }
...
```

You can see an example of how to implement composite objects in the examples directory.

Nulls, NonNulls and Nullables
-----------------------------

[](#nulls-nonnulls-and-nullables)

This package allows you to deal with nullable value objects.

First create a type of value object.

```
interface PhoneNumber extends ValueObject
{
}
```

Implement a non-null version of the value object.

```
final class NonNullPhoneNumber implements PhoneNumber
{
    use StringTrait;
}
```

Implement a null version of the value object.

```
final class NullPhoneNumber implements PhoneNumber
{
    use NullTrait;
}
```

Implement a nullable version of the value object.

```
final class NullablePhoneNumber extends Nullable implements PhoneNumber
{
    protected static function nonNullImplementation(): string
    {
        return NonNullPhoneNumber::class;
    }

    protected static function nullImplementation(): string
    {
        return NullPhoneNumber::class;
    }
}
```

This 'nullable' handles automatic creation of either a null or a non-null version of the interface based on the native input. For example:

```
$phoneNumber = NullablePhoneNumber::fromNative(null);
```

The `$phoneNumber` above will automatically use the `NullPhoneNumber` implementation specified above.

Or:

```
$phoneNumber = NullablePhoneNumber::fromNative('+44 73715525763');
```

The `$phoneNumber` above will automatically use the `NonNullPhoneNumber` implementation specified above.

Sets of value objects
---------------------

[](#sets-of-value-objects)

A set of value objects should implement the `Set` interface. It's just an extension of the `ValueObject` interface with a few simple additions.

```
interface Set extends ValueObject, \IteratorAggregate, \ArrayAccess, \Countable
{
    public function add($set);
    public function remove($set);
    public function contains(ValueObject $value): bool;
    public function toArray(): array;
}
```

- `add` Add values from another set to the current set.
- `remove` Remove all the values contained in another set from the current set.
- `contains` Returns `true` if the value exists in the current set.
- `toArray` Returns a simple PHP array containing all of the value objects.

The other interfaces that the `Set` interface extends from (`\IteratorAggregate`, `\ArrayAccess`, `\Countable`) are for accessing the set object as though it was an array.

### Non-null sets

[](#non-null-sets)

The library provides a default implementation of the interface.

```
final class SetOfLocations extends NonNullSet implements Set
{
    protected function typeToEnforce(): string
    {
        return Location::class;
    }

    public static function valuesShouldBeUnique(): bool
    {
        return true;
    }
}
```

There are two abstract methods that need to be implemented.

- `typeToEnforce` should return a string of the class name of the value object that you want to make a set of.
- `valuesShouldBeUnique` should return a boolean representing whether you want to force the set to be unique.

If the set is set to unique, if duplicate values are added to the set (at instantiation or through the `add` method) the duplicates are filtered out.

### Null and nullable sets

[](#null-and-nullable-sets)

Just like standard value objects there are some constructs to help with creating nullable and null sets. See the Nulls, NonNulls and Nullables section for more information.

- `NullableSet` The set equivalent of `Nullable`.
- `NullSetTrait` The set equivalent of the `NullTrait`.

### Usage of sets

[](#usage-of-sets)

#### Iteration, access and counting

[](#iteration-access-and-counting)

```
// Iteration
$set = new SetOfLocations([$one, $two]);
foreach($set as $value) {
    // TODO: Do something with each value object
}

// Access
$one = $set[0];
$two = $set[1];

//Counting
$count = count($set); // Returns 2
```

#### add

[](#add)

Merges another set.

```
$set = new SetOfLocations([$one, $two]);
$anotherSet = new SetOfLocations([$three]);
$mergedSet = $set->add($anotherSet);
count($mergedSet) // Equals: 3
```

#### remove

[](#remove)

Removes values from a set by using another set as reference values.

```
$set = new SetOfLocations([$one, $two, $three]);
$anotherSet = new SetOfLocations([$one]);
$remove = $set->remove($anotherSet);
count($remove) // Equals: 2
```

#### contains

[](#contains)

Checks whether a set contains a particular value object.

```
$set = new SetOfLocations([$one, $two, $three]);
$one = new Location(0);
$check = $set->contains($one);
```

###  Health Score

45

—

FairBetter than 93% of packages

Maintenance19

Infrequent updates — may be unmaintained

Popularity51

Moderate usage in the ecosystem

Community25

Small or concentrated contributor base

Maturity69

Established project with proven stability

 Bus Factor1

Top contributor holds 98.3% 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 ~65 days

Recently: every ~224 days

Total

18

Last Release

1977d ago

PHP version history (2 changes)0.0.0PHP ^7.1.0

0.5PHP ^7.1 || ^8.0

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/296186?v=4)[Chris Harrison](/maintainers/chrisharrison)[@chrisharrison](https://github.com/chrisharrison)

---

Top Contributors

[![chrisharrison](https://avatars.githubusercontent.com/u/296186?v=4)](https://github.com/chrisharrison "chrisharrison (59 commits)")[![jsandersuk](https://avatars.githubusercontent.com/u/22774080?v=4)](https://github.com/jsandersuk "jsandersuk (1 commits)")

###  Code Quality

TestsPHPUnit

Code StylePHP\_CodeSniffer

### Embed Badge

![Health badge](/badges/funeralzone-valueobjects/health.svg)

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

###  Alternatives

[morilog/jalali

This Package helps developers to easily work with Jalali (Shamsi or Iranian) dates in PHP applications, based on Jalali (Shamsi) DateTime class.

9201.2M45](/packages/morilog-jalali)[bruli/php-git-hooks

Git hooks for PHP projects.

675370.8k5](/packages/bruli-php-git-hooks)[nikolaposa/version

Value Object that represents a SemVer-compliant version number.

1406.4M16](/packages/nikolaposa-version)[prooph/common

Common classes used across prooph packages

852.2M27](/packages/prooph-common)[tomasnorre/crawler

Crawler extension for TYPO3

58397.5k1](/packages/tomasnorre-crawler)[sourceability/string-matcher

A library which makes it easy to use multiple approaches to find the best matching string

11537.4k](/packages/sourceability-string-matcher)

PHPackages © 2026

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