PHPackages                             q48academy/gdpr-privacy-by-design - 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. q48academy/gdpr-privacy-by-design

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

q48academy/gdpr-privacy-by-design
=================================

A Privacy by Design GDPR Class for PHP

01PHPCI failing

Since Jan 2Pushed 6y ago2 watchersCompare

[ Source](https://github.com/q48academy/gdpr-privacy-by-design)[ Packagist](https://packagist.org/packages/q48academy/gdpr-privacy-by-design)[ RSS](/packages/q48academy-gdpr-privacy-by-design/feed)WikiDiscussions master Synced yesterday

READMEChangelogDependenciesVersions (1)Used By (0)

GDPR with Privacy by Design in mind
===================================

[](#gdpr-with-privacy-by-design-in-mind)

GDPR / DSGVO Class in PHP
-------------------------

[](#gdpr--dsgvo-class-in-php)

### Disclaimer

[](#disclaimer)

This is a technical solution for a legal issue. This is no legal advice. Please check with your lawyer, if this processing is compliant with your environment.

### Key Consideration

[](#key-consideration)

GDPR is a class to comply with three main GDPR requirements

- Privacy by design
- Privacy by default
- Data mimimalism

The goal is to minify the potentially critical data, to avoid additional legal requirements if the respective data is not used anyway.

### The Core Process

[](#the-core-process)

All unneeded personal indentifiable information (pii) data should be wiped or anonymized.

If

1. this process is called before any other access and
2. other processes only access this kind of data via `$_SERVER` Superglobal

then you are not processing pii anymore.

This disables all GDPR requirements (after anonymizing) as GDPR only discusses personal identifiable information. Of course, the process of anonymizing and deletion has to be documented in your processes.

Again: Check this process with your lawyer.

If you anonymize it, you can choose to encrypt the raw data to have access to it later. All Access to the raw data will be logged by default.

### Documentation / Logging

[](#documentation--logging)

Each processing (read, transform, delete) of pii has to be documented and logged. This is even needed for anonymization or deletion. Logs have to document this process is in place and working.

But logging pii in a raw log to document that you are using pii responsibly is not an option. Leaking of pii has to be prevented.

We use Private/Public Key Encryption based on Sodium for each Log Entry so that only an Auditor can access the logging data.

You can provide the auditors public key in the key directory. You MUST NOT provide the private key of the auditor in the key directory. Keep it safe for the auditing process only.

All single log entries are a JSON array, signed by the local box and encrypted with the public key of the auditor.

You can forward the encrypted log entry to a logging service of your choice.

If logged locally, all logfiles are stored in daily directories and are deleted after two days.

Installation
============

[](#installation)

```
composer require q48academy/gdpr-privacy-by-design

```

Usage
=====

[](#usage)

This class takes care about processing potential personal information in a way that is compliant with

Wipe Information
----------------

[](#wipe-information)

WARNING: Wiping this information can have unexpected behavior in your application. Test carefully.

Basic Usage is to remove potential personal information from

```
Gdpr::wipeIp();

```

As you propably know, the `REMOTE_ADDR` does not always hold the correct data, if you are behind a proxy. You can forward the key corresponding to your environement.

```
Gdpr::wipeIp( 'HTTP_X_FORWARDED_FOR' );

```

The same methods can be used for other potentially pii holding keys.

```
Gdpr::wipeUserAgent();
Gdpr::wipeReferrer();
Gdpr::wipeQueryString();
Gdpr::wipeCookies();

```

Anonymize Information
---------------------

[](#anonymize-information)

WARNING: Anonymizing this information can have unexpected behavior in your application. Test carefully.

### Key functionality

[](#key-functionality)

there are three methods for each Key field.

- `getAnon[Key]` i.e. `getAnonIp()` to get the anonymized Data
- `setAnon[Key]` i.e. `setAnonIp()` to set the anonymized Data
- `getRaw[Key]` i.e. `getRawIp()` to get the raw Data after calling `setAnon[Key]` with the 'doEncrypt' Option

### Options

[](#options)

Different Keys provide different options. Options are passed as array to Getter and Setters

Options that are always available are:

- 'index' : The Key of the `$_SERVER` Array holding the information. i.e. `REMOTE_ADDR`
- 'doEncrypt' : The raw data shall be stored for later retrieval. It will be stored in a Key based in 'index' i.e. `GDPR_REMOTE_ADDR`

### IP

[](#ip)

#### Why

[](#why)

The IP is considered to be pii. With IPv6, this seems to be really clear.

#### Anonymizing Concept

[](#anonymizing-concept)

Set a specific number of Octets to '0'.

#### Basic usage

[](#basic-usage)

```
$gdpr = new Gdpr();
$anonIp = $gdpr->getAnonIp();

```

### Special Options

[](#special-options)

- 'rawIp' : The IP should not be taken from the `$_SERVER` Array but is given in raw. The information will be stored 'index' in i.e. `REMOTE_ADDR`
- 'v4' : The number of octets of an IPv4 Address that should be set to zero to anonymize. Default right now is 1.
- 'v6' : The number of octets of an IPv4 Address that should be set to zero to anonymize. Default right now is 4.

### User Agent

[](#user-agent)

#### Why

[](#why-1)

The User Agent is considered to be pii as it can be used to create a device fingerprint.

#### Anonymizing Concept

[](#anonymizing-concept-1)

Remove all Version information. Keep anonymized

- OS
- Mobile/Tablet
- Browser

Bots are not anonymized.

#### Basic usage

[](#basic-usage-1)

```
$gdpr = new Gdpr();
$anonIp = $gdpr->getAnonUserAgent();

```

Settings can be set via ENV

```
GDPR_DIR_KEYS=/etc/.keys
GDPR_DIR_LOGS=/var/log/gdpr

```

The class can also be initiated with two Settings

- keyDir
- logDir

    $gdpr = new Gdpr('/etc/.keys','/var/log/gdpr');

#### Installation Verification

[](#installation-verification)

```
$gdpr = new Gdpr();
$verifyLog = $gdpr->verify();
var_dump($verifyLog);

```

### Special Options

[](#special-options-1)

- 'rawUserAgent' : The User Agent should not be taken from the `$_SERVER` Array but is given in raw. The information will be stored in 'index' i.e. `HTTP_USER_AGENT`

### HTTP Referer

[](#http-referer)

#### Why

[](#why-2)

The Referer can contain pii.

#### Anonymizing Concept

[](#anonymizing-concept-2)

Remove all Path and Query information. Keep only host. If host matches whitelist, path information is kept.

#### Basic usage

[](#basic-usage-2)

```
$gdpr = new Gdpr();
$anonIp = $gdpr->getAnonReferrer();

```

### Special Options

[](#special-options-2)

- 'rawReferrer' : The Referrer should not be taken from the `$_SERVER` Array but is given in raw. The information will be stored in 'index' i.e. `HTTP_REFERER`
- 'whitelist' : an Array containing host names

### HTTP Referer

[](#http-referer-1)

#### Why

[](#why-3)

The Referer can contain pii.

#### Anonymizing Concept

[](#anonymizing-concept-3)

Remove all Path and Query information. Keep only host. If host matches whitelist, path information is kept.

#### Basic usage

[](#basic-usage-3)

```
$gdpr = new Gdpr();
$anonIp = $gdpr->getAnonReferrer();

```

### Special Options

[](#special-options-3)

- 'rawReferrer' : The Referrer should not be taken from the `$_SERVER` Array but is given in raw. The information will be stored in 'index' i.e. `HTTP_REFERER`
- 'whitelist' : an Array containing host names

### Query String

[](#query-string)

#### Why

[](#why-4)

The Query String can contain pii. i.e. `http://example.com/?mynameis=John+Smith`

#### Anonymizing Concept

[](#anonymizing-concept-4)

Remove all Query Keys. If key matches whitelist, path information is kept.

#### Basic usage

[](#basic-usage-4)

```
$gdpr = new Gdpr();
$anonIp = $gdpr->getAnonQueryString();

```

### Special Options

[](#special-options-4)

- 'rawQueryString' : The Query String should not be taken from the `$_SERVER` Array but is given in raw. The information will be stored in 'index' i.e. `QUERY_STRING`
- 'whitelist' : an Array containing query keys

### Request Uri

[](#request-uri)

#### Why

[](#why-5)

The Request Uri can contain pii. i.e. `http://example.com/path?mynameis=John+Smith`

#### Anonymizing Concept

[](#anonymizing-concept-5)

Remove Query String. If key matches whitelist, path information is kept.

ATTENTION: pii can be leaked with 404 requests as i.e. `http://example.com/mynameis/John+Smith`. This should be handled in your app.

#### Basic usage

[](#basic-usage-5)

```
$gdpr = new Gdpr();
$anonIp = $gdpr->getAnonRequestUri();

```

### Special Options

[](#special-options-5)

- 'rawRequestUri' : The Request Uri should not be taken from the `$_SERVER` Array but is given in raw. The information will be stored in 'index' i.e. `REQUEST_URI`
- 'whitelist' : an Array containing query keys

Accessing raw data
==================

[](#accessing-raw-data)

If raw data should be accessed, some information have to be provided and will be logged.

```
public function getRawIp(string $lawful_purpose, string $data_category, string $process_reason, string  $accessor ,array $options=[]):string

```

Lawfull purpose
---------------

[](#lawfull-purpose)

The lawful purposes from GDPR are provided as Constants

```
	const LAWFUL_PURPOSE_CONSENT 						= 'consent';
	const LAWFUL_PURPOSE_CONTRACTUAL_OBLIGATION 		= 'contract';
	const LAWFUL_PURPOSE_LEGAL_OBLIGATION 				= 'legal';
	const LAWFUL_PURPOSE_VITAL_INTEREST_OF_INDIVIDUAL 	= 'vital';
	const LAWFUL_PURPOSE_PUBLIC_INTEREST 				= 'public';
	const LAWFUL_PURPOSE_LEGITIMATE_INTEREST 			= 'interest';

```

Data categories
---------------

[](#data-categories)

The data categories from GDPR are provided as Constants

```
const DATA_CATEGORY_DEFAULT 	= 'default';
const DATA_CATEGORY_ETHNICITY 	= 'ethnicity';
const DATA_CATEGORY_POLITICS 	= 'politics';
const DATA_CATEGORY_RELIGION 	= 'religion';
const DATA_CATEGORY_LABOR_UNION = 'laborUnion';
const DATA_CATEGORY_HEALTH 		= 'health';
const DATA_CATEGORY_SEXUAL 		= 'sexual';

```

Process Reason
--------------

[](#process-reason)

The process reasons from GDPR are provided as Constants

```
const PROCESS_REASON_CREATE 	= 'create';
const PROCESS_REASON_READ 		= 'read';
const PROCESS_REASON_UPDATE 	= 'update';
const PROCESS_REASON_DELETE 	= 'delete';
const PROCESS_REASON_PUBLISH 	= 'publish';
const PROCESS_REASON_COMBINE 	= 'combine';
const PROCESS_REASON_ANONYMIZE 	= 'anonymize';
const PROCESS_REASON_ENCRYPT 	= 'encrypt';

```

Accessor
--------

[](#accessor)

The accessor is the Class|Fucntion|Author accessing this data

TODO: provide information where this process of accessing is documented

###  Health Score

17

—

LowBetter than 6% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity1

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity35

Early-stage or recently created project

 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.

### Community

Maintainers

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

---

Top Contributors

[![tiktoor](https://avatars.githubusercontent.com/u/427704?v=4)](https://github.com/tiktoor "tiktoor (9 commits)")

### Embed Badge

![Health badge](/badges/q48academy-gdpr-privacy-by-design/health.svg)

```
[![Health](https://phpackages.com/badges/q48academy-gdpr-privacy-by-design/health.svg)](https://phpackages.com/packages/q48academy-gdpr-privacy-by-design)
```

###  Alternatives

[hyperf/di

A DI for Hyperf.

182.8M594](/packages/hyperf-di)[pantheon-systems/quicksilver-pushback

Push commits made via the Pantheon dashboard back to original GitHub repository.

153.1M18](/packages/pantheon-systems-quicksilver-pushback)[heroyt/tournament-generator

A set of classes used to create multiple kinds of tournament brackets in PHP.

6615.2k](/packages/heroyt-tournament-generator)

PHPackages © 2026

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