PHPackages                             sinemacula/data-normalizer-php - 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. sinemacula/data-normalizer-php

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

sinemacula/data-normalizer-php
==============================

PHP library for consistent data normalization and formatting across names, emails, phone numbers, addresses, and other common data types.

v1.0.1(1mo ago)0147Apache-2.0PHPPHP ^8.3CI passing

Since Jun 7Pushed 3d agoCompare

[ Source](https://github.com/sinemacula/data-normalizer-php)[ Packagist](https://packagist.org/packages/sinemacula/data-normalizer-php)[ RSS](/packages/sinemacula-data-normalizer-php/feed)WikiDiscussions master Synced 1w ago

READMEChangelog (2)Dependencies (18)Versions (4)Used By (0)

Data Normalizer for PHP
=======================

[](#data-normalizer-for-php)

[![Latest Stable Version](https://camo.githubusercontent.com/7a3791e4266c76339ae5900367f7a67f0726f98432e209be21f93f347b109c31/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f73696e656d6163756c612f646174612d6e6f726d616c697a65722d7068702e737667)](https://packagist.org/packages/sinemacula/data-normalizer-php)[![Build Status](https://github.com/sinemacula/data-normalizer-php/actions/workflows/tests.yml/badge.svg?branch=master)](https://github.com/sinemacula/data-normalizer-php/actions/workflows/tests.yml)[![Quality Gates](https://github.com/sinemacula/data-normalizer-php/actions/workflows/quality-gates.yml/badge.svg?branch=master)](https://github.com/sinemacula/data-normalizer-php/actions/workflows/quality-gates.yml)[![Maintainability](https://camo.githubusercontent.com/c38277042613f753935a1a4d2676db9ca8f88e3732fac9111e80d10fc5ab03ac/68747470733a2f2f716c74792e73682f67682f73696e656d6163756c612f70726f6a656374732f646174612d6e6f726d616c697a65722d7068702f6d61696e7461696e6162696c6974792e737667)](https://qlty.sh/gh/sinemacula/projects/data-normalizer-php)[![Code Coverage](https://camo.githubusercontent.com/9a19a58d8d1f088c710672baae9a1375f6c59abe3b7076b383a1c9addf8ec6c0/68747470733a2f2f716c74792e73682f67682f73696e656d6163756c612f70726f6a656374732f646174612d6e6f726d616c697a65722d7068702f636f7665726167652e737667)](https://qlty.sh/gh/sinemacula/projects/data-normalizer-php)[![Total Downloads](https://camo.githubusercontent.com/5a4387dec7a7461b767bd2a64999e95c93e6f76b3e0e3f8016a4a3c43ce4d45b/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f73696e656d6163756c612f646174612d6e6f726d616c697a65722d7068702e737667)](https://packagist.org/packages/sinemacula/data-normalizer-php)

Consistent, deterministic normalization for the common data types every system handles slightly differently — names, emails, phone numbers, postal addresses, dates, currencies, and more. Each data type is encapsulated in a small, single-purpose normalizer behind one static facade, so `Normalizer::phone($value)` returns the same canonical output everywhere it is called.

The library is framework-agnostic — it has no dependency on Laravel or any other framework — and extensible: any consuming application can register its own normalizers without forking the package.

How It Works
------------

[](#how-it-works)

Every normalizer implements a single contract, `NormalizerInterface`, and is reached through the `Normalizer` facade. Calls are routed by name: `Normalizer::email($value)` resolves to the `Email` normalizer, dispatches to its `normalize()` method, and returns the result. Resolution is memoised, so the lookup cost is paid once per name per process.

A few rules hold across the surface:

- **Null means "could not normalize."** Every normalizer returns `null` for input it cannot produce a meaningful value from (non-strings, empty values, unparseable input) rather than throwing.
- **Canonical, idempotent output.** Each normalizer maps varied input to a single canonical form; re-normalizing an already-normalized value returns it unchanged.

Supported Normalizers
---------------------

[](#supported-normalizers)

NormalizerCallResult`clean``Normalizer::clean($value)`Collapses internal whitespace and trims the ends; the building block for the other normalizers`name``Normalizer::name($value)`Title-cases personal names; preserves `Mc` / `Mac` / `O'` prefixes, lowercases particles (`van`, `de`, `von`), and flips `Doe, John` to `John Doe``email``Normalizer::email($value)`Lowercases and strips spaces`phone``Normalizer::phone($value, ?$country)`Formats to E.164 via libphonenumber; defaults to the `US` region, returns `null` for invalid numbers`date``Normalizer::date($value)`Parses a set of known formats to `Y-m-d`; returns `null` for invalid calendar dates`timezone``Normalizer::timezone($value)`Resolves to a canonical IANA timezone identifier (case-insensitive)`addressLine``Normalizer::addressLine($value)`Title-cases the line and strips trailing commas`postalCode``Normalizer::postalCode($value, ?$country)`Validates and formats to the country's canonical form (UK/Canada spacing, US ZIP+4 hyphen); without a country, uppercases and trims`country``Normalizer::country($value)`Resolves a country name or code to its ISO 3166-1 alpha-2 code, with fuzzy matching for near-misses`administrativeArea``Normalizer::administrativeArea($value, ?$country)`Resolves a state / province / region name or code to its subdivision code (defaults to the `US` country)`companyName``Normalizer::companyName($value)`Normalizes legal suffixes (`Inc`, `LLC`, `Ltd`, `GmbH`, `SARL`)`jobTitle``Normalizer::jobTitle($value)`Title-cases titles while preserving acronyms (`CEO`, `IT`, `R&D`) and lowercasing stop words`currency``Normalizer::currency($value)`Validates and uppercases to an ISO 4217 currency code`ssn``Normalizer::ssn($value)`Strips to digits; preserves already-redacted values such as `***123`Installation
------------

[](#installation)

```
composer require sinemacula/data-normalizer-php
```

Usage
-----

[](#usage)

```
use SineMacula\Foundation\Normalizers\Normalizer;

Normalizer::name('SMITH, john');                // 'John Smith'
Normalizer::email(' John.Smith@Example.COM ');  // 'john.smith@example.com'
Normalizer::phone('(650) 253-0000');            // '+16502530000'
Normalizer::country('Untied States');           // 'US'  (fuzzy match)
Normalizer::postalCode('sw1a1aa', 'GB');        // 'SW1A 1AA'

Normalizer::clean('  not   a  phone  ');        // 'not a phone'
Normalizer::phone('not a phone');               // null
```

Extending
---------

[](#extending)

Register your own normalizers at application bootstrap. A custom normalizer is any class implementing `SineMacula\Foundation\Normalizers\Contracts\NormalizerInterface`:

```
use SineMacula\Foundation\Normalizers\Contracts\NormalizerInterface;
use SineMacula\Foundation\Normalizers\Normalizer;

class Iban implements NormalizerInterface
{
    public static function normalize(mixed $value, mixed $context = null): ?string
    {
        return is_string($value) ? strtoupper(str_replace(' ', '', $value)) : null;
    }
}

Normalizer::register('iban', Iban::class);

$iban = Normalizer::iban('de89 3704 0044 0532 0130 00'); // DE89370400440532013000
```

Registration is validated eagerly — `register()` throws an `InvalidNormalizerException` (an `InvalidArgumentException`subclass) immediately if the class does not implement `NormalizerInterface`, so misconfiguration surfaces at bootstrap rather than at call time. Registering the same name twice overwrites the earlier registration (last write wins).

Warning

Registered normalizers take precedence over the built-ins. Registering a name such as `phone` or `clean`intentionally replaces the built-in behaviour for every caller in the process — a deliberate feature, but one that can cause hard-to-trace differences in normalized output if used accidentally.

Register at bootstrap only. In long-running runtimes (Octane, Swoole, RoadRunner, queue workers) the registry is shared process state — treat it as write-once during boot and read-only thereafter. `Normalizer::flush()` clears all registrations and is intended for test isolation only.

For IDE completion of your custom normalizers, subclass the facade (it is intentionally non-final) purely to carry `@method` docblocks:

```
use SineMacula\Foundation\Normalizers\Normalizer as BaseNormalizer;

/**
 * @method static string|null iban(string $value)
 */
class Normalizer extends BaseNormalizer {}
```

Requirements
------------

[](#requirements)

- PHP ^8.3

Testing
-------

[](#testing)

```
composer test                # PHPUnit suite in parallel via Paratest
composer test:coverage       # suite with Clover coverage output
composer test:mutation       # Infection mutation gate (min MSI 90)
composer test:mutation:full  # full mutation suite without thresholds
composer check               # static analysis and lint via qlty
composer format              # format via qlty
composer smells              # duplication / complexity smells via qlty
composer bench               # PHPBench suite for the hot paths
composer bench:ci            # PHPBench with CI artifact dump
composer bench:smoke         # single-rev pass to verify every subject runs
```

Changelog
---------

[](#changelog)

See [CHANGELOG.md](CHANGELOG.md) for a list of notable changes.

Contributing
------------

[](#contributing)

Contributions are welcome. Please read [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines on branching, commits, code quality, and pull requests.

Security
--------

[](#security)

If you discover a security vulnerability, please report it responsibly. See [SECURITY.md](SECURITY.md) for the disclosure policy and contact details.

License
-------

[](#license)

Licensed under the [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0).

###  Health Score

44

—

FairBetter than 90% of packages

Maintenance95

Actively maintained with recent releases

Popularity14

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity51

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 51.6% 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 ~0 days

Total

2

Last Release

47d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/6262ea965c244b0c946a2f29a94da05e30846c066a0b59399466216654c78fe6?d=identicon)[sinemacula](/maintainers/sinemacula)

---

Top Contributors

[![sine-macula-dependencies[bot]](https://avatars.githubusercontent.com/in/4130001?v=4)](https://github.com/sine-macula-dependencies[bot] "sine-macula-dependencies[bot] (16 commits)")[![sinemacula-ben](https://avatars.githubusercontent.com/u/118753672?v=4)](https://github.com/sinemacula-ben "sinemacula-ben (15 commits)")

---

Tags

foundationsine maculadata normalizing

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/sinemacula-data-normalizer-php/health.svg)

```
[![Health](https://phpackages.com/badges/sinemacula-data-normalizer-php/health.svg)](https://phpackages.com/packages/sinemacula-data-normalizer-php)
```

###  Alternatives

[verbb/formie

The most user-friendly forms plugin for Craft.

101393.6k74](/packages/verbb-formie)[easycorp/easyadmin-bundle

Admin generator for Symfony applications

4.3k17.9M400](/packages/easycorp-easyadmin-bundle)[craftcms/cms

Craft CMS

3.6k3.6M3.2k](/packages/craftcms-cms)[commerceguys/tax

Tax library with a flexible data model, predefined tax rates, powerful resolving logic.

285781.2k](/packages/commerceguys-tax)[skeeks/cms

SkeekS CMS — control panel and tools based on php framework Yii2

13725.8k63](/packages/skeeks-cms)[sylius/addressing-bundle

Addressing and zone management for Symfony applications.

34235.1k5](/packages/sylius-addressing-bundle)

PHPackages © 2026

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