aria-php/constellation-client

PHP 8.2+ client library for Constellation scientific identifier resolution service

Maintainers

Package info

gitlab.com/aria-php/constellation-client

Issues

pkg:composer/aria-php/constellation-client

Transparency log

Statistics

Installs: 6

Dependents: 0

Suggesters: 0

Stars: 0

dev-main 2026-07-28 17:48 UTC

This package is auto-updated.

Last update: 2026-07-28 16:51:40 UTC


README

A simple, object-oriented PHP 8.2+ client library for the Constellation scientific identifier resolution and knowledge graph service.

Features

  • Async Discovery: Initiate identifier resolution jobs via the discovery endpoint
  • Graph Queries: Retrieve knowledge graph fragments with relationships and identifiers
  • Provenance Tracking: Query discovery events with full resolver provenance
  • JSON-LD Support: Access graph data in semantic web format
  • Type-Safe: Immutable value objects with full type hints
  • Exception-Based: Clear, specific exceptions for error handling
  • Zero Dependencies: Only requires Guzzle for HTTP (commonly available)

Installation

Install via Composer:

composer require constellation/php-client

Requires PHP 8.2 or higher.

Quick Start

use Constellation\Client;
use Constellation\Request\GraphQueryOptions;

// Initialize client
$client = new Client('http://localhost:8080');

// 1. Initiate async discovery
$discovery = $client->discovery()->discover('uniprot', 'P69905');
echo $discovery->jobId;  // UUID for tracking

// 2. Query knowledge graph
$graph = $client->graph()->get('uniprot', 'P69905');
echo $graph->entity->label;

// With query options
$options = (new GraphQueryOptions())
    ->depth(2)
    ->limit(50)
    ->offset(0);
$graph = $client->graph()->get('pdb', '1A3N', $options);

// 3. Track discovery provenance
$events = $client->provenance()->events(namespace: 'pdb', limit: 50);
foreach ($events->items as $event) {
    echo $event->resolver;      // 'PdbResolver'
    echo $event->timestamp;     // DateTime
    echo count($event->discovered);  // New identifiers found
}

API Reference

Client

Main entry point for all API operations.

$client = new Client(
    baseUrl: 'http://localhost:8080',
    httpClient: null,  // Optional custom Guzzle client
    timeout: 30        // Request timeout in seconds
);

$client->discovery();  // DiscoveryService
$client->graph();      // GraphService
$client->provenance(); // ProvenanceService

Discovery Service

Initiate asynchronous identifier resolution jobs.

$response = $client->discovery()->discover(
    namespace: 'uniprot',
    accession: 'P69905'
);

// Returns DiscoveryResponse
echo $response->jobId;              // UUID string
echo $response->status;             // 'queued'
echo $response->identifier->uri;    // 'https://identifiers.org/uniprot:P69905'

DiscoveryResponse fields:

  • jobId: string — Unique job identifier for tracking
  • status: string — Current status (typically 'queued')
  • identifier: Identifier — The resolved identifier with URI

Graph Service

Query entity-centric knowledge graph fragments.

// Standard JSON response
$graph = $client->graph()->get(
    namespace: 'uniprot',
    accession: 'P69905',
    options: new GraphQueryOptions()  // Optional
);

// JSON-LD response (semantic web format)
$ld = $client->graph()->getLd('pdb', '1A3N');

GraphQueryOptions (fluent builder):

$options = (new GraphQueryOptions())
    ->depth(2)      // 0-3 (default: 1)
    ->limit(50)     // 1-200 (default: 25)
    ->offset(0);    // 0+ (default: 0)

GraphResponse fields:

  • entity: Entity — The queried entity (id, type, label, metadata)
  • identifiers: IdentifierCollection — All identifiers for this entity
  • relationships: RelationshipCollection — Outbound and inbound relationships
  • pagination: array — Query depth, limit, offset

Entity fields:

  • id: int — Unique entity ID
  • type: string — Entity type ('Structure', 'Protein', 'Model', etc.)
  • label: string — Human-readable name
  • metadata: array — Resolver-specific data

Relationship fields:

  • predicate: string — Relationship type (e.g., 'MAPS_TO_PROTEIN', 'HAS_STRUCTURE')
  • level: int — Discovery depth (0-3)
  • sourceEntity: Entity — Source entity
  • targetEntity: Entity — Target entity

IdentifierCollection methods:

$collection->getItems();           // Identifier[]
$collection->getTotal();           // int
$collection->count();              // int
$collection->isEmpty();            // bool
$collection->filterByNamespace('pdb');  // Identifier[]

RelationshipCollection methods:

$collection->getOutbound();        // Relationship[] (from queried entity)
$collection->getInbound();         // Relationship[] (to queried entity)
$collection->getAll();             // Relationship[]
$collection->filterOutboundByPredicate('MAPS_TO_PROTEIN');
$collection->filterInboundByPredicate('HAS_STRUCTURE');
$collection->count();              // int

Provenance Service

Query discovery events with provenance metadata.

$response = $client->provenance()->events(
    namespace: 'pdb',          // Optional filter
    accession: '1A3N',         // Optional filter
    resolver: 'PdbResolver',   // Optional filter
    limit: 50,                 // 1-200 (default: 50)
    offset: 0                  // 0+ (default: 0)
);

foreach ($response->items as $event) {
    echo $event->resolver;        // Resolver name
    echo $event->version;         // Resolver version
    echo $event->timestamp;       // DateTimeImmutable
    echo $event->input->namespace;
    foreach ($event->discovered as $id) {
        echo $id->namespace;      // New identifiers found
    }
    echo $event->metadata['source'];  // API source URL
}

ProvenanceResponse fields:

  • query: array — Filter parameters used
  • count: int — Number of events returned
  • items: ProvenanceEvent[] — Discovery events

ProvenanceEvent fields:

  • id: int — Event record ID
  • timestamp: DateTimeImmutable — When discovered
  • resolver: string — Resolver name
  • version: string — Resolver version
  • input: Identifier — The identifier that was resolved
  • discovered: Identifier[] — New identifiers found
  • metadata: array — Resolver-specific metadata

Error Handling

The library throws specific exceptions for different error types:

use Constellation\Exception\InterfaceException;
use Constellation\Exception\DiscoveryException;
use Constellation\Exception\GraphException;
use Constellation\Exception\ProvenanceException;
use Constellation\Exception\NetworkException;

try {
    $client->discovery()->discover('uniprot', 'P69905');
} catch (DiscoveryException $e) {
    // Discovery endpoint error
    echo $e->getMessage();
} catch (NetworkException $e) {
    // HTTP/network error (timeout, connection failed, etc.)
    echo $e->getMessage();
    echo $e->getPrevious();  // Original exception
} catch (InterfaceException $e) {
    // Catch all Constellation errors
    echo $e->getMessage();
}

Configuration

Custom HTTP Client

For advanced customization, provide your own Guzzle client:

use GuzzleHttp\Client as GuzzleClient;

$httpClient = new GuzzleClient([
    'timeout' => 60,
    'headers' => ['User-Agent' => 'MyApp/1.0'],
    'proxy' => 'http://proxy.example.com:8080',
]);

$client = new Client('http://api.example.com', $httpClient);

Base URL

Default: http://localhost:8080

$client = new Client('https://constellation.example.com:8443');

Request Timeout

Default: 30 seconds

$client = new Client('http://localhost:8080', timeout: 60);

Testing

Run tests with PHPUnit:

composer install
./vendor/bin/phpunit

Tests include:

  • Unit Tests: Value object construction, serialization, builder validation
  • Integration Tests: Full service workflows with fixture-based mocked HTTP responses

All integration tests use pre-recorded API responses (fixtures) for deterministic, offline testing.

Value Objects

All response models are immutable value objects:

$identifier = new Identifier('uniprot', 'P69905');
$identifier->namespace;  // 'uniprot'
$identifier->accession;  // 'P69905'
$identifier->uri;        // Generated URI
// All properties are readonly

$entity = new Entity(1, 'Protein', 'Human Hemoglobin', ['species' => 'Homo sapiens']);
$entity->id;        // 1
$entity->type;      // 'Protein'
$entity->label;     // 'Human Hemoglobin'
$entity->metadata;  // ['species' => 'Homo sapiens']

JSON Serialization

Convert responses to JSON:

$graph = $client->graph()->get('pdb', '1A3N');
$json = json_encode($graph->toArray());

$event = $response->items[0];
$eventJson = json_encode($event->toArray());

JSON-LD Support

Access semantic web linked data format:

$ld = $client->graph()->getLd('pdb', '1A3N');

echo $ld['@context'];     // RDF context
echo $ld['@id'];          // Entity URI
echo $ld['@type'];        // Entity type
echo $ld['label'];        // Entity label
foreach ($ld['identifier'] ?? [] as $id) {
    echo $id['@id'];      // Identifier URI
}
foreach ($ld['relationship'] ?? [] as $rel) {
    echo $rel['predicate'];  // Relationship type
    echo $rel['target'];     // Target entity URI
}

Contributing

Contributions are welcome! Please ensure:

  • All tests pass
  • New code includes unit/integration tests
  • PHPDoc comments on all public methods
  • Code follows PSR-12 standards

License

MIT

Related