PHPackages                             acdh-oeaw/uri-normalizer - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. acdh-oeaw/uri-normalizer

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

acdh-oeaw/uri-normalizer
========================

A simple class for normalizing external entity reference sources' URIs (Geonames, GND, etc. URIs).

4.2.0(4d ago)07.8k↑1057.1%4MITPHPPHP ^8.1CI passing

Since Nov 18Pushed 4d ago4 watchersCompare

[ Source](https://github.com/acdh-oeaw/uriNormalizer)[ Packagist](https://packagist.org/packages/acdh-oeaw/uri-normalizer)[ Docs](https://github.com/acdh-oeaw/uriNormalizer)[ RSS](/packages/acdh-oeaw-uri-normalizer/feed)WikiDiscussions master Synced 2d ago

READMEChangelog (10)Dependencies (36)Versions (21)Used By (4)

URI Normalizer
==============

[](#uri-normalizer)

[![Latest Stable Version](https://camo.githubusercontent.com/224b7a34c2a0474bad304cbe1f6e269c1f8ceb66aa398f38b3df54c86e43d676/68747470733a2f2f706f7365722e707567782e6f72672f616364682d6f6561772f7572692d6e6f726d616c697a65722f762f737461626c65)](https://packagist.org/packages/acdh-oeaw/uri-normalizer)[![Build Status](https://github.com/acdh-oeaw/uriNormalizer/actions/workflows/test.yml/badge.svg)](https://github.com/acdh-oeaw/uriNormalizer/actions/workflows/test.yml)[![Coverage Status](https://camo.githubusercontent.com/6552b87b6d2b13f1e4223644db4bf10361717ba8b155e206fee7c8bfa88ef4ea/68747470733a2f2f636f766572616c6c732e696f2f7265706f732f6769746875622f616364682d6f6561772f7572694e6f726d616c697a65722f62616467652e7376673f6272616e63683d6d6173746572)](https://coveralls.io/github/acdh-oeaw/uriNormalizer?branch=master)[![License](https://camo.githubusercontent.com/48f3e47fe89c3708b2daf54823fb7cc790f8ae536e89f81c65f097b4ced99fe6/68747470733a2f2f706f7365722e707567782e6f72672f616364682d6f6561772f7572692d6e6f726d616c697a65722f6c6963656e7365)](https://packagist.org/packages/acdh-oeaw/uri-normalizer)

A class for **normalizing named entity URIs** from services like Geonames, GND, VIAF, ORCID, etc. and **retrieving RDF metadata** from them.

By default the rules from the [arche-assets](https://github.com/acdh-oeaw/arche-assets) library are used by you can supply your own ones.

Any PSR-16 compatible cache can be used to speed up normalization/retrieval of reccuring URIs. A combined in-memory and persistent sqlite-based cache implementation is provided as well.

Context
-------

[](#context)

While looking at the named entity database services it's quite often difficult to tell which URL is a canonical URI for a given named entity.

Just let's take a quick look at a bunch (there are definitely more) of Geonames URLs describing exactly same Geonames named entity with id 2761369:

-
-
-
-
-
-
-
-
-
-

Which one of them is **the right one**? The actual answer is quite simple - **the one used as an RDF triples subject in the RDF metadata returned by a given service.**So the first aim of this package is to provide a tool for transforming any URL coming from a given service and transform it into the canonical URI used by the service in the RDF metadata it returns.

But here we come to another issue - how to fetch the RDF metadata for a given named entity knowing its URI?

For some services (like ORCID or VIAF) it can be done just with an [HTTP content negotation](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept) by requesting response in one of supported RDF formats. For other though you need to know a service-specific content negotation method, e.g. in Geonames you need to append `/about.rdf` to the canonical URI. The second aim of this package is to allow you to retrieve RDF metadata from named entity URIs/URLs without being bothered by all those service-specific peculiarities. And as such a retrieval involves quite some time, a caching option is also provided.

Automatically generated documentation
-------------------------------------

[](#automatically-generated-documentation)

Installation
------------

[](#installation)

```
composer require acdh-oeaw/uri-normalizer

```

Usage
-----

[](#usage)

```
###
# Initialization
###
$normalizer = new \acdhOeaw\uriNormalizer\UriNormalizer();

###
# string URL normalization
###
// returns 'https://sws.geonames.org/2761369/'
echo $normalizer->normalize('http://geonames.org/2761369/vienna.html');

###
# Retrieve parsed/raw RDF metadata from URI/URL
###
// print parsed RDF metadata retrieved from the geonames
$metadata = $normalizer->fetch('http://geonames.org/2761369/vienna.html');
echo $metadata;

// get a PSR-7 request fetching the RDF metadata for a given geonames URL
$request = $normalizer->resolve('http://geonames.org/2761369/vienna.html');
echo $request->getUri() . "\n";

###
# Use your own normalization rules
# and supply a custom Guzzle HTTP client (can be any PSR-18 one) supplying authentication
###
$rules = [
  [
    "match"   => "^https://(?:my.)own.namespace/([0-9]+)(?:/.*)?$",
    "replace" => "https://own.namespace/\\1",
    "resolve" => "https://own.namespace/\\1",
    "format"  => "application/n-triples",
  ],
];
$client = new \GuzzleHttp\Client(['auth' => ['login', 'password']]);
$cache  = null;
$normalizer = new \acdhOeaw\uriNormalizer\UriNormalizer($rules, '', $client, $cache);
// returns 'https://own.namespace/123'
echo $normalizer->normalize('https://my.own.namespace/123/foo');
// obviously won't work but if the https://own.namespace would exist,
// it would be queried with the HTTP BASIC auth as set up above
$normalizer->fetch('https://my.own.namespace/123/foo');

###
# Use cache
###
// use default TTL of 600 seconds
// if cache file is not specified, an in-memory cache is created
$cache = new \acdhOeaw\uriNormalizer\UriNormalizerCache('db.sqlite', 600);
$normalizer = new \acdhOeaw\uriNormalizer\UriNormalizer(cache: $cache);
// first retrieval should take 0.1-1 second depending on your connection speed
$t = microtime(true);
$metadata = $normalizer->fetch('http://geonames.org/2761369/vienna.html');
$t = (microtime(true) - $t);
echo $metadata . "\ntime: $t s\n";
// second retrieval should be very quick thanks to in-memory cache
$t = microtime(true);
$metadata = $normalizer->fetch('http://geonames.org/2761369/vienna.html');
$t = (microtime(true) - $t);
echo $metadata . "\ntime: $t s\n";
// a completely separate UriNormalizer instance still benefits from the persistent
// sqlite cache
$cache2 = new \acdhOeaw\UriNormalizerCache('db.sqlite');
$normalizer2 = new \acdhOeaw\UriNormalizer(cache: $cache);
$t = microtime(true);
$metadata = $normalizer2->fetch('http://geonames.org/2761369/vienna.html');
$t = (microtime(true) - $t);
echo $metadata . "\ntime: $t s\n";

###
# As a global singleton
###
// initialization is done with init() instead of a constructor
// the init() takes same parameters as the constructor
\acdhOeaw\uriNormalizer\UriNormalizer::init();
// all other methods (gNormalize(), gFetch() and gResolve()) also work in
// the same way and take same parameters as their non-static counterparts
//
// returns 'https://sws.geonames.org/2761369/'
echo \acdhOeaw\uriNormalizer\UriNormalizer::gNormalize('http://geonames.org/2761369/vienna.html');
// fetch and parse RDF metadata
echo \acdhOeaw\uriNormalizer\UriNormalizer::gFetch('http://geonames.org/2761369/vienna.html');
// just resolve
echo \acdhOeaw\uriNormalizer\UriNormalizer::gResolve('http://geonames.org/2761369/vienna.html')->getUri();

###
# Configure 3 retry attempts on HTTP 429 with a delay increasing with every retry (1.5, 3 and 4.5 seconds)
###
$retryCfg = new \acdhOeaw\UriNormalizerRetryConfig(
    number: 3,
    delay: 1.5,
    scale: \acdhOeaw\UriNormalizerRetryConfig::SCALE_MULTI,
    on: [429],
);
$normalizer = new \acdhOeaw\uriNormalizer\UriNormalizer(retryCfg: $retryCfg);
echo $normalizer->resolve('http://geonames.org/2761369/vienna.html')->getUri();
```

###  Health Score

57

—

FairBetter than 97% of packages

Maintenance99

Actively maintained with recent releases

Popularity24

Limited adoption so far

Community18

Small or concentrated contributor base

Maturity76

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~127 days

Recently: every ~26 days

Total

20

Last Release

4d ago

Major Versions

1.1.1 → 2.0.02022-10-13

2.0.0 → 3.0.0-RC12024-01-24

3.6.0 → 4.0.02026-03-18

PHP version history (3 changes)1.0.0PHP &gt;= 7.1

2.0.0PHP &gt;= 8.0

3.1.0PHP ^8.1

### Community

Maintainers

![](https://www.gravatar.com/avatar/f1f662e3acb95efd9208cdcd2c97437db366044aea705985251760efcbd23070?d=identicon)[zozlak](/maintainers/zozlak)

---

Top Contributors

[![zozlak](https://avatars.githubusercontent.com/u/6503177?v=4)](https://github.com/zozlak "zozlak (70 commits)")

---

Tags

arche

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/acdh-oeaw-uri-normalizer/health.svg)

```
[![Health](https://phpackages.com/badges/acdh-oeaw-uri-normalizer/health.svg)](https://phpackages.com/packages/acdh-oeaw-uri-normalizer)
```

###  Alternatives

[laravel/framework

The Laravel Framework.

34.8k543.8M20.1k](/packages/laravel-framework)[civicrm/civicrm-core

Open source constituent relationship management for non-profits, NGOs and advocacy organizations.

751291.4k43](/packages/civicrm-civicrm-core)[shopware/core

Shopware platform is the core for all Shopware ecommerce products.

585.6M577](/packages/shopware-core)[oat-sa/tao-core

TAO core extension

66143.7k124](/packages/oat-sa-tao-core)[eslazarev/wildberries-sdk

Wildberries OpenAPI clients (generated).

273.0k](/packages/eslazarev-wildberries-sdk)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
