Download the PHP package nieknijland/rdw-opendata-php without Composer

On this page you can find all versions of the php package nieknijland/rdw-opendata-php. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package rdw-opendata-php

rdw-opendata-php

Latest Version on Packagist Tests Total Downloads

A typed PHP client for the RDW Open Data Voertuigen datasets. Avoids magic Dutch field strings: every dataset has a generated field enum with English case names, every record is a typed value object, and dates are CarbonImmutable in UTC.

Installation

Requires PHP 8.4+.

Quick start

Configuration

The HTTP layer raises NiekNijland\RDW\Exceptions\RateLimitException on HTTP 429 (with retryAfterSeconds extracted from the Retry-After header) and HttpException on any other non-2xx response.

Supported datasets

Method on Rdw RDW dataset id Record class
registeredVehicles() m9d7-ebf2 Records\RegisteredVehicle
registeredVehicleFuels() 8ys7-d773 Records\RegisteredVehicleFuel
registeredVehicleAxles() 3huj-srit Records\RegisteredVehicleAxle
registeredVehicleBodyworks() vezc-m2t6 Records\RegisteredVehicleBodywork
registeredVehicleBodyworkSpecifications() jhie-znh9 Records\RegisteredVehicleBodyworkSpecification
registeredVehicleClasses() kmfi-hrps Records\RegisteredVehicleClass
registeredVehicleSubcategories() 2ba7-embk Records\RegisteredVehicleSubcategory
registeredVehicleSpecialFeatures() 7ug8-2dtt Records\RegisteredVehicleSpecialFeature
registeredVehicleTrackSets() 3xwf-ince Records\RegisteredVehicleTrackSet
odometerJudgementExplanations() jqs4-4kvw Records\OdometerJudgementExplanation

Query builder

The builder is immutable: every chained method returns a clone. You can share a partially built query across functions safely.

Where predicates

Method Emits Notes
where($field, $value, $op = '=') field op value Operator must be one of =, !=, <>, <, <=, >, >=, LIKE, NOT LIKE. Rejects null — use whereNull instead.
whereIn($field, $values) field IN (…) Rejects an empty list.
whereNotIn($field, $values) field NOT IN (…)
whereNull($field) / whereNotNull($field) field IS [NOT] NULL
whereBetween($field, $min, $max) field BETWEEN x AND y Encodes dates as Socrata datetime literals.
whereNotBetween($field, $min, $max) field NOT BETWEEN x AND y
whereLike($field, $pattern) field LIKE '…' SQL % wildcards, case-sensitive.
whereStartsWith($field, $prefix) starts_with(field, '…') Case-sensitive.
whereContains($field, $sub) contains(field, '…') Case-insensitive per Socrata.
whereAny(fn ($q) => …) ((a) OR (b) OR …) OR-group. The callback must return the chained builder — the builder is immutable, a void closure throws.
whereNot(fn ($q) => …) NOT ((a) AND (b)) Same callback contract as whereAny. Combine with whereAny inside for NOT (a OR b).
whereRaw($expression) passes through Use RDW field keys (not English aliases).
search($query) sets $q Socrata full-text search across every string column. Whitespace-tokenized; rows must contain every token.

Every field-typed argument takes a case of the dataset's generated field enum — RegisteredVehicleField, RegisteredVehicleFuelField, etc. The generated enums live under src/Fields/; PascalCase case names map to the RDW field key, e.g. RegisteredVehicleField::CommercialNamehandelsbenaming.

Selection, ordering, pagination

Method Emits Notes
select($field, …) $select=fields Variadic; chained calls accumulate. Pass field-enum cases.
selectRaw($expr, $alias = null) appends to $select Use for arbitrary SoQL projections. Aliases must match [A-Za-z_][A-Za-z0-9_]*.
groupBy($field, …) $group=fields Combine with the aggregate helpers below.
orderBy($field, $direction = Asc) $order=field DIR SortDirection::Asc / SortDirection::Desc.
orderByRaw($expr) appends to $order Use for arbitrary SoQL like count DESC.
limit($n) $limit=$n Must be ≥ 1.
offset($n) $offset=$n Must be ≥ 0.

Aggregates and projections

Combine these with groupBy() + getProjection() for analytic queries:

Method Emits
count($field = null, $alias = 'count') count(field) or count(*)
countDistinct($field, $alias = 'count') count(distinct field)
sum($field, $alias = 'sum') sum(field)
avg($field, $alias = 'avg') avg(field)
min($field, $alias = 'min') min(field)
max($field, $alias = 'max') max(field)
distinct() prepends distinct to $select (requires at least one select() call).
havingRaw($expr) sets $having; reference the aliases you used above.
selectRaw($expr, $alias = null) escape hatch for arbitrary SoQL projections.

Executing the query

Method Returns Notes
get() list<TRecord> Single page, hydrated.
first() ?TRecord Adds $limit=1.
exists() bool Single-row probe; skips hydration.
pluck($field) list<scalar\|CarbonImmutable\|null> One column's values, cast through the same ValueCaster records use.
iterate($pageSize = 1000) Generator<int, TRecord> Pages lazily. Outer limit() is a hard ceiling. See Pagination.
getProjection() list<array<string, mixed>> Raw associative rows. Use for aggregate / groupBy / selectRaw queries that don't fit the record schema.
toSoqlParams() array<string, string> The $select/$where/$order/… map as it will be sent. Useful for debugging — see the Cookbook.

Boolean fields

Fields backed by RDW's Ja/Nee text values are typed as bool in the records and in the where-clauses:

Dates

Calendar-date fields (*_dt) hydrate to CarbonImmutable at midnight UTC. When you pass any DateTimeInterface to where() for a date field, it is serialized as a Socrata datetime literal:

Raw SoQL escape hatch

For Socrata expressions the typed API does not model — date_extract, lower, upper, geospatial predicates, CASE expressions, etc. — fall back to whereRaw / selectRaw / orderByRaw / havingRaw. Raw fragments take RDW field keys, not English aliases:

To bypass the typed builder entirely — for ad-hoc queries against a dataset that doesn't yet have a typed wrapper, or to inspect the metadata document RDW publishes — use the two passthrough methods on Rdw:

Pagination

get() issues a single request and returns one page. For large result sets use iterate(), which yields hydrated records lazily and pages internally:

An outer ->limit(N) is respected as a hard ceiling.

Relations

A registered vehicle is the entry point for every other dataset. Relations return pre-filtered query builders, so you can chain more filters before hitting the API:

Relations throw RdwException when a required join key is null on the source record — that prevents accidentally querying "everything where kenteken IS NULL".

Cookbook

Worked examples against the live RDW API. Numbers come from a run on 2026-05-16.

Count: how many white VW Ups are insured?

Group + having: the top-5 brands with more than 100k registrations

Fuzzy model search with OR-group

whereContains is case-insensitive (Socrata contains()), whereStartsWith is case-sensitive (Socrata starts_with()). Use whereLike with % wildcards if you need SQL-style patterns.

Date range: VWs first admitted in 2020-2024

Pluck: every license plate of a model variant

pluck of a date field returns CarbonImmutable instances; the cast goes through the same ValueCaster the typed records use.

Existence probe (no hydration)

Full-text search across all string columns

$q is tokenized on whitespace; rows must contain every token. It's slow on big datasets without an app token — narrow it with a where() first.

Lazy iteration over a large fleet

An outer ->limit(N) caps the iteration.

Debugging: inspect the SoQL the builder will emit

toSoqlParams() returns the exact $select/$where/$order/etc. that will be sent to Socrata, without performing the request.

Exceptions

All exceptions extend NiekNijland\RDW\Exceptions\RdwException. Catch the base class for blanket handling, or the specific type for control flow.

Exception Thrown when
HttpException Non-2xx response (excluding 429) or transport failure. Carries statusCode and responseBody.
RateLimitException HTTP 429. Carries retryAfterSeconds extracted from the Retry-After header.
DatasetNotFoundException Asking the registry for an unknown dataset id.
RdwException Catch-all base: invalid relation join keys, malformed JSON, scalar payloads from Socrata, etc.
MissingFieldOverrideException Generator-time only: RDW exposes a field with no matching override.

Schema introspection (for AI / dynamic consumers)

SchemaRegistry is the entry point for anything that needs to reason about the dataset shape at runtime — e.g. an LLM-driven natural-language → SoQL pipeline that has to know which fields exist, how they're typed, and which values they accept.

ValueVocabulary::closed(...) marks small Dutch code lists (vehicle type, colors) whose full set is known; ValueVocabulary::examples(...) marks fields like brand and commercial name where the list is too large to enumerate and consumers get a curated sample to anchor prompts or autocompletion. The library never enforces the vocabulary during hydration: RDW occasionally introduces new values, and a strict cast would turn that into a crash. Treat exhaustive as a hint, not a contract.

Schema regeneration

Field enums and record classes live under src/Fields/ and src/Records/. They are generated from the curated override classes under src/Schema/Overrides/ and validated against checked-in metadata snapshots under metadata/.

To refresh after a change to overrides (or after pulling a new RDW schema snapshot):

Generation fails loudly when an RDW metadata field has no override or when an override points at a field RDW no longer exposes — that is the public API stability contract from the implementation plan.

Testing

The default suite is fully offline and uses mocked HTTP. To run live tests against opendata.rdw.nl, add your own tests behind an environment guard; the package does not ship live tests in the default suite.

Architecture

Changelog

Please see CHANGELOG for what has changed recently.

License

The MIT License (MIT). Please see License File for more information.


All versions of rdw-opendata-php with dependencies

PHP Build Version
Package Version
Requires php Version ^8.4
guzzlehttp/guzzle Version ^7.8
nesbot/carbon Version ^3.0
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package nieknijland/rdw-opendata-php contains the following files

Loading the files please wait ...