php-xapi/repository-api
PHP package defining repository interfaces and abstractions for the php-xapi ecosystem, helping implement storage and query backends for xAPI statements and Learning Record Stores (LRS).
This package provides the xAPI statement repository contract and related domain wiring used to persist and retrieve Statement objects. It is not an Eloquent package and ships no Laravel migrations or models; you own the storage layer.
Start by looking at:
StatementRepositoryInterface in the installed package source.php-xapi/model v1.0 Statement and StatementId classes.php-xapi/exception v1.0 NotFoundException.php-xapi/test-fixtures v1.0 for repository tests.Minimal setup for a Laravel app:
composer require php-xapi/repository:^0.3
composer require --dev php-xapi/test-fixtures:^1.0
Confirm Composer resolves:
composer show php-xapi/model php-xapi/exception php-xapi/test-fixtures
The first practical use case is implementing an Eloquent-backed repository:
use XApi\Model\Statement;
use XApi\Model\StatementId;
use XApi\Exception\NotFoundException;
use XApi\Repository\StatementRepositoryInterface;
class EloquentStatementRepository implements StatementRepositoryInterface
{
public function storeStatement(Statement $statement): StatementId
{
// Persist the statement, then return its StatementId.
}
public function findStatementById(StatementId $statementId): Statement
{
// Load by string id, hydrate and return a Statement.
}
public function findVoidedStatementById(StatementId $voidedStatementId): Statement
{
// Load the voided statement or throw NotFoundException.
}
}
Bind the interface in a service provider:
$this->app->bind(
StatementRepositoryInterface::class,
EloquentStatementRepository::class
);
Use the interface as the integration boundary. Controllers, jobs, and services should depend on StatementRepositoryInterface, not on a concrete repository or removed base class.
Convert strings to StatementId at the edge of your application:
use XApi\Model\StatementId;
$statementId = new StatementId($request->route('statementId'));
$statement = $repository->findStatementById($statementId);
Keep the repository thin and map between xAPI domain objects and your Laravel persistence model:
Statement from the stored payload before returning it.StatementId from storeStatement(), not a raw string.XApi\Exception\NotFoundException when a lookup misses, not a Laravel ModelNotFoundException.A typical controller flow:
public function store(StoreStatementRequest $request, StatementRepositoryInterface $repository)
{
$statement = $this->statementFactory->fromRequest($request);
$statementId = $repository->storeStatement($statement);
return response()->json(['id' => (string) $statementId], 201);
}
For tests, use php-xapi/test-fixtures to build valid statements and assert against StatementId instances:
$id = $repository->storeStatement($fixtureStatement);
$this->assertInstanceOf(StatementId::class, $id);
If you use Doctrine, use php-xapi/repository-doctrine instead of implementing Doctrine mapping in this package. For Laravel, an Eloquent or query-builder-backed implementation is usually the shortest path.
MappedStatement, MappedVerb, and the old StatementRepository base class. Doctrine users should move mapping concerns to php-xapi/repository-doctrine.StatementId objects. Passing strings to findStatementById() or findVoidedStatementById() will cause type errors. Cast route parameters and request input before calling the repository.storeStatement() now returns a StatementId, not a string. Update callers, tests, and JSON responses accordingly.XApi\Exception\NotFoundException, not the old package-local exception. Grep for the old namespace after upgrading.StatementRepository class while also saying it was removed. Verify your installed vendor tree. Treat StatementRepositoryInterface as the stable target; if your code extended the old base class, replace it with your own implementation.php-xapi/model and php-xapi/test-fixtures at ^1.0. Mixed old/new xAPI packages commonly produce signature and class-not-found errors. Use composer why-not php-xapi/model 1.0 when resolution fails.StatementRepositoryInterface in a service provider. Do not bind the removed concrete class. Keep the repository stateless so it can be resolved normally or as a singleton without request leakage.StatementId objects directly from Laravel JSON responses unless your response layer casts them to strings.NotFoundException deliberately. Let unexpected database errors surface or convert them to your application’s error contract, but do not silently return empty statements.MappedStatement, MappedVerb, StatementRepository, old NotFoundException, and string-based statement id assumptions. Then run repository tests against StatementId values.How can I help you explore Laravel packages today?