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.