PHP implementation of the W3C Provenance Data Model (PROV-DM)

Maintainers

Package info

github.com/amateescu/prov

pkg:composer/amateescu/prov

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.0.0 2026-04-23 09:25 UTC

This package is auto-updated.

Last update: 2026-04-23 09:49:31 UTC


README

Release CI

PHP implementation of the W3C Provenance Data Model (PROV-DM).

PROV-DM describes where things come from: entities (things you care about), activities (things that happen), and agents (who's responsible). Relations like wasGeneratedBy and wasAttributedTo connect them to form a provenance graph.

This library provides a fluent builder for assembling that graph, round-trip serializers for PROV-JSON, PROV-N, and PROV-XML (plus serialize-only PROV-JSON-LD), document operations (merge, flatten, semantic equality), and a partial PROV-CONSTRAINTS validator.

Requirements

  • PHP 8.4+
  • ext-dom (only if you use XmlSerializer)

Installation

composer require amateescu/prov

Quick start

use Prov\Format;
use Prov\Prov;

$builder = Prov::documentBuilder();
$builder->namespace('ex', 'http://example.org/');
$builder->entity('ex:article');
$builder->activity('ex:writing', startTime: new DateTimeImmutable('2024-01-15'));
$builder->agent('ex:alice');
$builder->wasGeneratedBy(entity: 'ex:article', activity: 'ex:writing');
$builder->wasAssociatedWith(activity: 'ex:writing', agent: 'ex:alice');

$doc = $builder->build();

$json = Prov::serialize($doc, Format::Json);
echo $json;
// Other formats: Format::ProvN, Format::Xml, Format::JsonLd.

$parsed = Prov::deserialize($json, Format::Json);

Always pass relation arguments by name. PROV-DM fixes a per-relation positional order that does not follow subject-before-object. wasGeneratedBy takes (entity, activity) but used takes (activity, entity): the two sit in opposite orders even though they connect the same two records. Positional calls silently invert the relation:

// These two lines describe DIFFERENT facts, even though both identifiers are the same:
$builder->wasGeneratedBy('ex:article', 'ex:writing'); // article wasGeneratedBy writing ✓
$builder->used('ex:article', 'ex:writing');           // article used writing ✗ (reversed)

// Always use named arguments:
$builder->wasGeneratedBy(entity: 'ex:article', activity: 'ex:writing');
$builder->used(activity: 'ex:writing', entity: 'ex:article');

Format support

Format Serialize Deserialize
PROV-JSON yes yes
PROV-N yes yes
PROV-XML yes yes
PROV-JSON-LD yes no (would require an RDF-aware parser)

Document operations

use Prov\Operation\DocumentOperations;
use Prov\Operation\DocumentComparator;

$merged = DocumentOperations::merge($docA, $docB);
$flat = DocumentOperations::flatten($docWithBundles);            // throws if Mentions present
$flat = DocumentOperations::flattenDroppingMentions($docWithBundles);

DocumentComparator::equals($a, $b);  // structural (semantic) equality

Validation

$result = Prov::validate($document);

if (!$result->isValid()) {
    foreach ($result->getViolations() as $violation) {
        echo "[C{$violation->constraintId}] {$violation->message}\n";
    }
}

// Or throw if the document has any violations:
Prov::validate($document)->throwIfInvalid();  // raises ConstraintViolationException

Coverage is partial: rules that need transitive graph reasoning over derivation chains aren't implemented, so isValid() === true only means no checked rule was violated. Use ConstraintValidator::implementedConstraints() or ::unsupportedConstraints() to see the exact set.

Builder tips

Blank nodes (anonymous records):

$e = $builder->blank();          // _:b1
$builder->entity($e);
$builder->wasGeneratedBy(entity: $e, activity: 'ex:writing');

Bundles:

$builder
    ->entity('ex:e1')
    ->withBundle('ex:b1', fn ($b) => $b
        ->entity('ex:e2')
        ->wasGeneratedBy(entity: 'ex:e2', activity: 'ex:a1'))
    ->build();

DocumentBuilder::build() and BundleBuilder::build() are single-use; a second call throws LogicException.

Learn more

Every public class carries an inline docblock explaining what it's for. The most useful starting points:

  • Prov\Prov: the facade used in the examples above
  • Prov\Builder\DocumentBuilder: the full set of record and relation methods
  • Prov\Format: supported serialization formats
  • Prov\Constraint\ConstraintValidator: what each PROV-CONSTRAINTS rule checks

Development

Before submitting a PR, run composer check (format, lint, analyze, tests).

License

This library is made available under the MIT License. Please see LICENSE for more information.