PHPackages                             xp-forge/partial - 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. xp-forge/partial

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

xp-forge/partial
================

Partial types

v4.0.0(6y ago)07.0k[2 issues](https://github.com/xp-forge/partial/issues)BSD-3-ClausePHPPHP &gt;=7.0.0

Since Apr 4Pushed 5y ago1 watchersCompare

[ Source](https://github.com/xp-forge/partial)[ Packagist](https://packagist.org/packages/xp-forge/partial)[ Docs](http://xp-framework.net/)[ RSS](/packages/xp-forge-partial/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (3)Versions (22)Used By (0)

Partials: Compile-time metaprogramming
======================================

[](#partials-compile-time-metaprogramming)

[![Build Status on TravisCI](https://camo.githubusercontent.com/a9683d07769ebc1a72a81ff44b44c1c9fb88f2325e50be4c29f5094d9feddc45/68747470733a2f2f7365637572652e7472617669732d63692e6f72672f78702d666f7267652f7061727469616c2e737667)](http://travis-ci.org/xp-forge/partial)[![XP Framework Module](https://raw.githubusercontent.com/xp-framework/web/master/static/xp-framework-badge.png)](https://github.com/xp-framework/core)[![BSD Licence](https://raw.githubusercontent.com/xp-framework/web/master/static/licence-bsd.png)](https://github.com/xp-framework/core/blob/master/LICENCE.md)[![Requires PHP 7.0+](https://raw.githubusercontent.com/xp-framework/web/master/static/php-7_0plus.png)](http://php.net/)[![Latest Stable Version](https://camo.githubusercontent.com/1a1ebc7f115fd53102f143f5c90ecc0d27b0d6d83ef270849fbffbbc7376e6ba/68747470733a2f2f706f7365722e707567782e6f72672f78702d666f7267652f7061727469616c2f76657273696f6e2e706e67)](https://packagist.org/packages/xp-forge/partial)

For situations where more logic than just "compiler-assisted copy&amp;paste" using [PHP's traits](http://php.net/traits) is necessary, this library provides a syntax that expand dynamically based on the containing class at compile time.

Partial flavors
---------------

[](#partial-flavors)

The partials provided by this library's are divided in two flavors: Kinds and composeables.

- **Kinds** define the general concept of a type. You can say, e.g.: This type ***is*** a list of something, or a reference to something. Or, to use more concrete examples: The `Customers` class is a list of customers (encapsulated by `Customer` instances), and `Name` is a reference to (a string) containing a name.
- **Composeables** can be used alone or in combination to extend a base type or a kind. You can say, e.g. This type comes ***with*** a certain functionality. Again, using a realistic use-case: The `Person` class comes with `toString()`, `compareTo()` and `hashCode()` methods.

Regardless of their flavor, some partials are actually implemented by a regular PHP trait, others are dynamically created at runtime. However, the syntax for both is `use [Containing-Type]\[is-or-with]\[Partial-Name]`.

Walk-through
------------

[](#walk-through)

The `Box` trait creates a value object wrapping around exactly one member. It creates a one-arg constructor, and a `value()` for retrieving the value, and includes appropriate `hashCode()`, `compareTo()` and `toString()` implementations.

Writing this:

```
namespace example;

use lang\partial\Box;
use lang\Value;

class Name implements Value {
  use Name\is\Box;

  public function personal() { return '~' === $this->value{0}; }
}
```

...is equivalent to:

```
namespace example;

use lang\Value;

class Name implements Value {
  protected $value;

  public function __construct($value) { $this->value= $value; }

  public function value() { return $this->value; }

  public function personal() { return '~' === $this->value{0}; }

  public function hashCode() { /* ... */ }

  public function compareTo($value) { /* ... */ }

  public function toString() { /* ... */ }
}
```

The parametrized `Accessors` trait creates accessors for all instance members.

---

Writing this:

```
namespace example;

use lang\partial\Accessors;

class Wall {
  use Wall\with\Accessors;

  private $name, $type, $posts;

  public function __construct(
    Name $name,
    Type $type,
    Posts $posts
  ) {
    $this->name= $name;
    $this->type= $type;
    $this->posts= $posts;
  }
}
```

...is equivalent to:

```
namespace example;

class Wall {
  private $name, $type, $posts;

  public function __construct(
    Name $name,
    Type $type,
    Posts $posts
  ) {
    $this->name= $name;
    $this->type= $type;
    $this->posts= $posts;
  }

  public function name() { return $this->name; }

  public function type() { return $this->type; }

  public function posts() { return $this->posts; }
}
```

If the constructor consists solely of assignments, you can include the `Constructor` trait and remove it. The parameters will be declared in the order the fields are declared: top to bottom, left to right in the source code.

---

Writing this:

```
namespace example;

use lang\partial\Constructor;

class Author {
  use Author\with\Constructor;

  private $handle, $name;
}
```

...is equivalent to:

```
namespace example;

class Author {
  private $handle, $name;

  public function __construct($handle, $name) {
    $this->handle= $handle;
    $this->name= $name;
  }
}
```

To combine all these, you can use the `Value` trait, which a) creates a constructor with all members as parameters, b) accessors for reading these, and c) implements the `hashCode()`, `compareTo()` and `toString()` methods.

The `ListOf` trait creates a list of elements which can be accessed by their offset, iterated by `foreach`, and offers `equals()` and `toString()` default implementations.

---

Writing this:

```
namespace example;

use lang\partial\ListOf;

class Posts implements \lang\Value, \IteratorAggregate {
  use Posts\is\ListOf;
}
```

...is equivalent to:

```
namespace example;

class Posts implements \lang\Value, \IteratorAggregate {
  private $backing;

  public function __construct(...$elements) {
    $this->backing= $elements;
  }

  public function present() { return !empty($this->backing); }

  public function size() { return sizeof($this->backing); }

  public function at($offset) {
    if (isset($this->backing[$offset])) {
      return $this->backing[$offset];
    }
    throw new ElementNotFoundException(…);
  }

  public function first() {
    if (empty($this->backing)) {
      throw new ElementNotFoundException(…);
    }
    return $this->backing[0];
  }

  public function getIterator() {
    foreach ($this->backing as $element) {
      yield $element;
    }
  }

  public function compareTo($value) { /* ... */ }

  public function toString() { /* ... */ }

  public function hashCode() { /* ... */ }
}
```

The `Builder` trait will add a static `with()` method to your class, generating a fluent interface to create instances. This is especially useful in situation where there are a lot of constructor parameters.

The `Comparators` trait adds static `by[Member]` methods returning util.Comparator instances for each member. These instances can be combined using *then* (`Post::byDate()->then(Post::byAuthor())`) or reversed (`Post::byDate()->reverse()`).

```
namespace example;

use lang\partial\Accessors;
use lang\partial\Builder;
use lang\partial\Comparators;

class Post {
  use Wall\with\Accessors;
  use Wall\with\Builder;
  use Wall\with\Comparators;

  private $author, $text, $date;

  public function __construct($author, $text, Date $date) {
    $this->author= $author;
    $this->text= $text;
    $this->date= $date;
  }
}
```

The `ListIndexedBy` trait creates a list of elements which can be queried by name, also overloading iteration and creating `equals()` and `toString()` in a sensible manner. The class needs to implement the abstract `index` method and return a string representing the name.

```
namespace example;

use lang\partial\ListIndexedBy;

class Walls implements \IteratorAggregate {
  use Walls\is\ListIndexedBy;

  protected function index($wall) { return $wall->name()->value(); }
}
```

Putting it all together, we can see the API:

```
use util\data\Sequence;

$post= Post::with()->author('Timm')->text('Hello World!')->date(Date::now())->create();

$walls= new Walls(
  new Wall(new Name('one'), Type::$OPEN, new Posts()),
  new Wall(new Name('two'), Type::$CLOSED, new Posts($post))
);

$walls->present();        // TRUE, list is not empty
$walls->size();           // 2
$walls->provides('one');  // TRUE, wall named one found
$walls->provides('zero'); // FALSE, no such wall
$walls->first();          // Wall(name => Name("one"), type => OPEN)
$walls->named('two');     // Wall(name => Name("two"), type => CLOSED)
$walls->named('three');   // ***ElementNotFoundException

foreach ($walls as $wall) {
  Console::writeLine('== ', $wall->name()->value(), ' wall (', $wall->type(), ') ==');
  Sequence::of($wall->posts())->sorted(Post::byDate())->each(function($post) {
    Console::writeLine('Written by ', $post->author(), ' on ', $post->date());
    Console::writeLine($post->text());
    Console::writeLine();
  });
}
```

See also
--------

[](#see-also)

-
-

###  Health Score

32

—

LowBetter than 72% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity18

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity67

Established project with proven stability

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

Recently: every ~260 days

Total

20

Last Release

2229d ago

Major Versions

v0.8.0 → v1.0.02016-02-21

v1.1.2 → v2.0.02016-07-23

v2.1.1 → v3.0.02017-06-04

v3.1.1 → v4.0.02020-04-10

PHP version history (3 changes)v0.1.0PHP &gt;=5.6.0

v0.6.0PHP &gt;=5.5.0

v4.0.0PHP &gt;=7.0.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/07d18d882c8b4aaf3466432f64018214f2771eda333202175431ee7233795376?d=identicon)[thekid](/maintainers/thekid)

---

Top Contributors

[![thekid](https://avatars.githubusercontent.com/u/696742?v=4)](https://github.com/thekid "thekid (190 commits)")

---

Tags

accessorlombokphptraitxp-frameworkmodulexp

### Embed Badge

![Health badge](/badges/xp-forge-partial/health.svg)

```
[![Health](https://phpackages.com/badges/xp-forge-partial/health.svg)](https://phpackages.com/packages/xp-forge-partial)
```

PHPackages © 2026

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