Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Oparl Client Laravel Package

sitepark/oparl-client

A PHP client for OParl, the open standard for parliamentary information systems. Query OParl APIs to retrieve bodies, meetings, papers, and agendas through a clean, typed interface that integrates smoothly into Laravel applications.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a plain PHP library (PSR-4, Composer-installed), not a Laravel package — there is no service provider, no config file, and no facade. Version 1.0.0 is the first stable release and requires PHP 8.1+.

composer require sitepark/oparl-php-client

Where to look first:

  1. The OParl client class (added in 6b10119) — this is your entry point. It is constructed around a base URL pointing at an OParl System endpoint (e.g. https://parliament.example.org/oparl/v1.0/system).
  2. The object type classes (9db1a89) — System, Body, LegislativeTerm, Organization, Person, Membership, Meeting, AgendaItem, Paper, Consultation, File, Location. Every response you get back is one of these.
  3. The reference handling (7b16805, e14f718) — most OParl properties are URLs to other objects, not inline data. Understanding how references are resolved lazily is the single most important concept.

First use case: fetch the system description and enumerate the bodies it declares.

$client = new OparlClient('https://parliament.example.org/oparl/v1.0/system');

$system = $client->getSystem();          // System object
$bodies = $system->getBody();            // a paginated list of Body references

foreach ($bodies as $body) {
    // iterating a list lazily resolves each reference
    dump($body->getName(), $body->getWebsite());
}

Register the client as a singleton in a small service provider so you don't rebuild it per request:

$this->app->singleton(OparlClient::class, fn () => new OparlClient(
    config('services.oparl.system_url')
));

Implementation Patterns

Lazy reference walking. OParl responses are graphs linked by URLs. Prefer navigating from a root object over hand-building URLs; the client knows how to resolve references and will follow .../paper/123 links correctly. When you need the URL itself (for logging or storage), use the reference's identifier rather than triggering resolution.

Iterating paginated lists. Lists are paginated and the client follows next links (1fd2e3b). Just foreach — but always set an upper bound or break for large bodies, because a full crawl of a German parliament can be tens of thousands of papers.

foreach ($body->getMeeting() as $meeting) {
    if ($meeting->getStart() < now()->subYear()) {
        break; // lists are typically ordered; don't pull the whole archive
    }
    // ...
}

Persisting responses instead of re-fetching. Because objects can be restored from JSON (e14f718), the natural pattern is: fetch once, json_encode into a json/longText column or a cache entry keyed by the object URL, then restore later. This is essential for anything resembling a sync job — the upstream API is slow and rate-sensitive.

$paper = $client->getPaper($url);
Paper::updateOrCreate(
    ['oparl_id' => $paper->getId()],
    ['payload' => json_encode($paper), 'synced_at' => now()]
);

// later, without a network call:
$paper = PaperObject::fromJson($model->payload);

Query parameters for filtering. The client supports query parameters (7b16805) — use them at the source instead of filtering in PHP. Server-side filtering is dramatically cheaper than crawling and discarding.

Wrap it in your own DTO/Repository layer. Do not let OParl object classes leak into Blade views or API resources. OParl is a moving external contract; map into Eloquent models or plain DTOs at the boundary so an upstream breaking change is a one-file fix.

Queue the sync. Put client calls in jobs (ShouldQueue) with retries and backoff. The package has no built-in retry, caching, or rate limiting — that's your application's job.

Gotchas and Tips

Parsing is deliberately tolerant — don't mistake it for validation. Dates, URLs, and property mapping all silently accept bad input (b778065, 9f82445). A malformed startDate will likely come back as null rather than throwing. Guard downstream code and log unexpected nulls; treat OParl data as untrusted input.

References are not eagerly loaded. A Paper gives you a Consultation reference, not the consultations. Naively looping over references to build a table is an N+1 over HTTP — batch by list endpoints, or persist locally and query the DB.

Pagination cycle detection uses requested URLs only (d29c17d). If a server returns a different URL that resolves to the same page (redirects, changing sort orders, session IDs), you may loop. Always cap iterations in your own crawl loop as a backstop.

List links vs. single objects. The client now rejects a list link where a single-object class is expected (0d124e3). This is a good thing, but it means an upstream schema mistake surfaces as an exception mid-crawl — catch per-object, log, and continue rather than aborting the whole sync.

BOM and invalid UTF-8 are tolerated (74bf686), but your database may not be. Run payloads through your own normalisation before persisting, and be wary of json_encode failures on MySQL utf8mb4 if you round-trip raw upstream bytes.

Debug output shows only reference URLs (add724e). That keeps dump()/dd() readable, but it also means "the property is there" doesn't imply "the object behind it was fetched." Don't debug missing data by staring at a dump — check whether the reference was ever resolved.

No configuration surface. There is no publishable config, no HTTP client swap documented, no timeout/retry knobs advertised. Set timeouts and headers at the transport level (or wrap the client) rather than hunting for options.

Extension points are thin by design. Since 1.0.0 is the first tag and the API is object-model-first, plan to subclass or decorate the client rather than patching the package — and pin ^1.0 in composer.json, since a 1.x minor is where tolerant-parsing behaviour is most likely to shift.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core