Skip to content

Examples

Runnable examples live in the docs/examples/ directory of the repository and are included here verbatim. A test compiles every example on each CI run, so they cannot drift from the code.

Build a graph of linked objects

<?php

declare(strict_types=1);

use LambdaTwelve\OneRecord\Model\Builder\Embedded;
use LambdaTwelve\OneRecord\Model\Builder\ObjectBuilder;
use LambdaTwelve\OneRecord\Model\Builder\Values;
use LambdaTwelve\OneRecord\Model\LocalGraph;
use LambdaTwelve\OneRecord\Model\UuidIriMinter;
use LambdaTwelve\OneRecord\Vocabulary\Generated\Cargo;
use LambdaTwelve\OneRecord\Vocabulary\Generated\CodeLists\MeasurementUnitCode;

// A master air waybill with its shipment, one piece and the shipper, linked by
// local keys. Every property is checked against the ontology as it is set.
$graph = LocalGraph::create()
    ->add('waybill', ObjectBuilder::of(Cargo::Waybill)
        ->set(Cargo::waybillPrefix, '020')
        ->set(Cargo::waybillNumber, '12345675')
        ->set(Cargo::waybillType, Values::individual(Cargo::MASTER))
        ->set(Cargo::shipment, Values::ref('shipment')))
    ->add('shipment', ObjectBuilder::of(Cargo::Shipment)
        ->set(Cargo::goodsDescription, 'Machine parts')
        ->set(Cargo::totalGrossWeight, Values::quantity(190.5, MeasurementUnitCode::KGM))
        ->set(Cargo::waybill, Values::ref('waybill'))
        ->add(Cargo::pieces, Values::ref('piece-1'))
        ->add(Cargo::involvedParties, Embedded::of(Cargo::Party)
            ->set(Cargo::partyRole, Values::code('ParticipantIdentifier', 'SHP'))
            ->set(Cargo::partyDetails, Values::ref('shipper'))))
    ->add('piece-1', ObjectBuilder::of(Cargo::Piece)
        ->set(Cargo::grossWeight, Values::quantity(190.5, MeasurementUnitCode::KGM))
        ->set(Cargo::coload, false))
    ->add('shipper', ObjectBuilder::of(Cargo::Company)
        ->set(Cargo::name, 'ACME Machines'));

// Mint URIs under the host's base URL; the same seed always yields the same URIs.
$resolved = $graph->resolve(new UuidIriMinter('https://1r.example.com', seed: 'shipment-AER-1'));

echo $resolved->root()->toJson();

Run a server and read an object as a partner

<?php

declare(strict_types=1);

use LambdaTwelve\OneRecord\Api\Permission;
use LambdaTwelve\OneRecord\Model\Builder\ObjectBuilder;
use LambdaTwelve\OneRecord\Model\Builder\Values;
use LambdaTwelve\OneRecord\Rdf\Iri;
use LambdaTwelve\OneRecord\Server\DataHolder;
use LambdaTwelve\OneRecord\Server\InMemory\InMemoryServer;
use LambdaTwelve\OneRecord\Server\ServerConfig;
use LambdaTwelve\OneRecord\Server\Spi\Agent;
use LambdaTwelve\OneRecord\Server\Spi\Authenticator;
use LambdaTwelve\OneRecord\Server\SystemClock;
use LambdaTwelve\OneRecord\Vocabulary\Generated\Cargo;
use LambdaTwelve\OneRecord\Vocabulary\Generated\CodeLists\MeasurementUnitCode;
use Nyholm\Psr7\Factory\Psr17Factory;
use Nyholm\Psr7\ServerRequest;
use Psr\EventDispatcher\EventDispatcherInterface;
use Psr\Http\Message\ServerRequestInterface;

// Who is calling? In production this is JwtAuthenticator (RS256 bearer tokens);
// here a header stands in so the example runs without keys.
$authenticator = new class implements Authenticator {
    public function authenticate(ServerRequestInterface $request): ?Agent
    {
        $agent = $request->getHeaderLine('X-Agent');

        return $agent === '' ? null : new Agent(new Iri($agent));
    }
};
// Any PSR-14 dispatcher; the SDK raises events such as LogisticsObjectCreated.
$dispatcher = new class implements EventDispatcherInterface {
    public function dispatch(object $event): object
    {
        return $event;
    }
};

// Any PSR-17 factory does; nyholm/psr7 is used here.
$factory = new Psr17Factory();
$holder = new Iri('https://1r.example.com/logistics-objects/holder');
$server = new InMemoryServer(
    new ServerConfig('https://1r.example.com', $holder, dataHolderType: Cargo::Company),
    $authenticator,
    new SystemClock(),
    $dispatcher,
    $factory,
    $factory,
);
$server->policy->addInternal($holder);

// The host publishes its own data through the PHP API.
$dataHolder = new DataHolder($server->services);
$piece = $dataHolder->create(
    ObjectBuilder::of(Cargo::Piece)
        ->set(Cargo::goodsDescription, 'Machine parts')
        ->set(Cargo::grossWeight, Values::quantity(190.5, MeasurementUnitCode::KGM))
        ->build(new Iri('https://1r.example.com/logistics-objects/piece-1')),
);

// A partner may read it once the access policy says so.
$partner = new Iri('https://1r.partner.example/logistics-objects/forwarder');
$server->policy->allow($partner, $piece->object->iri, [Permission::GetLogisticsObject]);

// $server->handler is the PSR-15 handler to mount; here it is called directly.
$request = new ServerRequest('GET', 'https://1r.example.com/logistics-objects/piece-1', [
    'Accept' => 'application/ld+json; version=2.3.0',
    'X-Agent' => $partner->value,
]);
$response = $server->handler->handle($request);

echo $response->getStatusCode(), ' ', $response->getHeaderLine('Content-Type'), "\n";
echo 'Type: ', $response->getHeaderLine('Type'), "\n";
echo 'Revision: ', $response->getHeaderLine('Revision'), "\n";
echo $response->getBody(), "\n";

More examples are added as each feature lands; see the roadmap.