Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
5c5bf62
Added support for Snowflake identifiers and all variations
puzzledpolymath Jul 16, 2025
09c697e
Updated UUID and ULID keeping psalm satisfied
puzzledpolymath Jul 16, 2025
ddb97c1
Added tests for Snowflake identifiers as well as updated tests for UU…
puzzledpolymath Jul 16, 2025
5bc9eb0
Updated documentation
puzzledpolymath Jul 16, 2025
eca8ae4
Updated composer dependencies
puzzledpolymath Jul 22, 2025
76ff381
Added classes for handling identifier default values
puzzledpolymath Jul 27, 2025
70758a1
Integrated defaults into identifier classes
puzzledpolymath Jul 27, 2025
289505f
Added tests for identifier defaults
puzzledpolymath Jul 27, 2025
f9b8cc4
Updated documentation
puzzledpolymath Jul 27, 2025
df00756
Updated documentation
puzzledpolymath Jul 27, 2025
759cd17
Add base Snowflake listener
roxblnfk Aug 10, 2025
ed571a2
Refactor SnowflakeDiscord
roxblnfk Aug 10, 2025
5130bbb
Refactor SnowflakeInstagram
roxblnfk Aug 10, 2025
bf24d19
Refactor other Snowflakes
roxblnfk Aug 10, 2025
e51f831
Refactor UUID listeners
roxblnfk Aug 10, 2025
61ec5ef
style(php-cs-fixer): fix coding standards
Aug 10, 2025
fb6df50
Provides fixes after merged changes broke a lot of things
puzzledpolymath Aug 19, 2025
907158d
Provides fixes after merged changes broke a lot of things
puzzledpolymath Aug 19, 2025
259a8ba
Refactor Snowflace typecasters
roxblnfk Sep 9, 2025
376a260
Refactor UUID listeners
roxblnfk Sep 9, 2025
ea368f8
Update dependencies
puzzledpolymath Nov 1, 2025
e0b77a0
Update docblock description for each Snowflake identifier
puzzledpolymath Nov 1, 2025
70611d2
Updated Ulid following a consistent structure
puzzledpolymath Nov 1, 2025
a5e9f10
Updated Ulid following a consistent structure
puzzledpolymath Nov 1, 2025
bbbbc77
Adjustments to keep Psalm happy
puzzledpolymath Nov 2, 2025
c0e8efd
Adjusted code placement
puzzledpolymath Nov 2, 2025
233fce4
Renamed static factory method and added abstract getTypecast method
puzzledpolymath Nov 2, 2025
8b2d2c4
Implemented UUIDv1 factory and getTypecast
puzzledpolymath Nov 2, 2025
0966faf
Implemented UUIDv2 factory and getTypecast, ensure listener arg local…
puzzledpolymath Nov 2, 2025
46d4d3f
Implemented UUIDv3 factory and getTypecast, made namespace and name o…
puzzledpolymath Nov 2, 2025
8bc4244
Implemented UUIDv4 factory and getTypecast
puzzledpolymath Nov 2, 2025
163bed8
Implemented UUIDv5 factory and getTypecast, made namespace and name o…
puzzledpolymath Nov 2, 2025
605adbf
Implemented UUIDv6 factory and getTypecast
puzzledpolymath Nov 2, 2025
18e62bb
Implemented UUIDv7 factory and getTypecast
puzzledpolymath Nov 2, 2025
7fd75d3
Ensure SnowflakeDiscord getProcessId returns int within range
puzzledpolymath Nov 2, 2025
2aac843
Added UUID factory to base UUID Listener
puzzledpolymath Nov 2, 2025
2d61e62
Updated UUIDv1 Listener to use factory, changed return type to more s…
puzzledpolymath Nov 2, 2025
af7cd67
Updated UUIDv2 Listener to use factory, changed return type to more s…
puzzledpolymath Nov 2, 2025
e430af8
Updated UUIDv2 Listener to use factory, changed return type to more s…
puzzledpolymath Nov 2, 2025
47d01a5
Updated UUIDv2 Listener to use factory, changed return type to more s…
puzzledpolymath Nov 2, 2025
ef86bdd
Updated UUIDv5 Listener to use factory, changed return type to more s…
puzzledpolymath Nov 2, 2025
6240cd8
Updated UUIDv6 Listener to use factory, changed return type to more s…
puzzledpolymath Nov 2, 2025
3c87203
Updated UUIDv7 Listener to use factory, changed return type to more s…
puzzledpolymath Nov 2, 2025
21bc7b7
Additional test fixtures
puzzledpolymath Nov 2, 2025
f2c23d8
Updated test cases
puzzledpolymath Nov 2, 2025
2ecded9
Updated documentation
puzzledpolymath Nov 2, 2025
73c830e
style(php-cs-fixer): fix coding standards
Nov 2, 2025
cb7c1c3
Removed superfluous PHP docs
puzzledpolymath Nov 2, 2025
e54123e
Removed unused imports
puzzledpolymath Nov 2, 2025
1962700
Improved test structure for listener classes
puzzledpolymath Nov 2, 2025
8adf742
Merge remote-tracking branch 'origin/snowflake-identifier' into snowf…
puzzledpolymath Nov 2, 2025
17fc49e
Improved documentation format and content
puzzledpolymath Nov 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 132 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# Cycle ORM Entity Behavior Identifier
[![Latest Stable Version](https://poser.pugx.org/cycle/entity-behavior-Identifier/version)](https://packagist.org/packages/cycle/entity-behavior-identifier)
[![Latest Stable Version](https://poser.pugx.org/cycle/entity-behavior-identifier/version)](https://packagist.org/packages/cycle/entity-behavior-identifier)
[![Build Status](https://github.com/cycle/entity-behavior-identifier/workflows/build/badge.svg)](https://github.com/cycle/entity-behavior-identifier/actions)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/cycle/entity-behavior-identifier/badges/quality-score.png?b=1.x)](https://scrutinizer-ci.com/g/cycle/entity-behavior-identifier/?branch=1.x)
[![Codecov](https://codecov.io/gh/cycle/entity-behavior-identifier/graph/badge.svg)](https://codecov.io/gh/cycle/entity-behavior)
<a href="https://discord.gg/TFeEmCs"><img src="https://img.shields.io/badge/discord-chat-magenta.svg"></a>

Expand All @@ -19,13 +18,100 @@ composer require cycle/entity-behavior-identifier

## Snowflake Examples

**Snowflake:** A distributed ID generation system developed by Twitter that produces 64-bit unique, sortable identifiers. Each ID encodes a timestamp, machine ID, and sequence number, enabling high-throughput, ordered ID creation suitable for large-scale distributed applications.
### Generic
A flexible Snowflake format that can use a node identifier and any epoch offset, suitable for various applications requiring unique identifiers. Default values for `node` and `epochOffset` can be defined globally via the `\Cycle\ORM\Entity\Behavior\Identifier\Listener\SnowflakeGeneric::setDefaults()` method.

> **Note:** Support for Snowflake identifiers will arrive soon, stay tuned.
```php
use Cycle\Annotated\Annotation\Column;
use Cycle\Annotated\Annotation\Entity;
use Cycle\ORM\Entity\Behavior\Identifier;
use Ramsey\Identifier\Snowflake;

#[Entity]
#[Identifier\SnowflakeGeneric(field: 'id', node: 1, epochOffset: 1738265600000)]
class User
{
#[Column(type: 'snowflake', primary: true)]
private Snowflake $id;
}
```

### Discord
Snowflake identifier for Discord's platform (voice, text, video), starting from epoch `2015-01-01`. Can incorporate a worker and process ID's to generate distinct Snowflakes. Default values for `workerId` and `processId` can be defined globally via the `\Cycle\ORM\Entity\Behavior\Identifier\Listener\SnowflakeDiscord::setDefaults()` method.

```php
use Cycle\Annotated\Annotation\Column;
use Cycle\Annotated\Annotation\Entity;
use Cycle\ORM\Entity\Behavior\Identifier;
use Ramsey\Identifier\Snowflake;

#[Entity]
#[Identifier\SnowflakeDiscord(field: 'id', workerId: 12, processId: 24)]
class User
{
#[Column(type: 'snowflake', primary: true)]
private Snowflake $id;
}
```

### Instagram
Snowflake identifier for Instagram's photo and video sharing platform, with an epoch starting at `2011-08-24`. Can incorporate a shard ID to generate distinct Snowflakes. Default values for `shardId` can be defined globally via the `\Cycle\ORM\Entity\Behavior\Identifier\Listener\SnowflakeInstagram::setDefaults()` method.

```php
use Cycle\Annotated\Annotation\Column;
use Cycle\Annotated\Annotation\Entity;
use Cycle\ORM\Entity\Behavior\Identifier;
use Ramsey\Identifier\Snowflake;

#[Entity]
#[Identifier\SnowflakeInstagram(field: 'id', shardId: 16)]
class User
{
#[Column(type: 'snowflake', primary: true)]
private Snowflake $id;
}
```

### Mastodon
Snowflake identifier for Mastodon's decentralized social network, generated within a database to ensure uniqueness and approximate order within 1ms. Can include a table name for distinct sequences per table; IDs are unique on a single database but not guaranteed across multiple machines. Default values for `tableName` can be defined globally via the `\Cycle\ORM\Entity\Behavior\Identifier\Listener\SnowflakeMastodon::setDefaults()` method.

```php
use Cycle\Annotated\Annotation\Column;
use Cycle\Annotated\Annotation\Entity;
use Cycle\ORM\Entity\Behavior\Identifier;
use Ramsey\Identifier\Snowflake;

#[Entity]
#[Identifier\SnowflakeMastodon(field: 'id', tableName: 'users')]
class User
{
#[Column(type: 'snowflake', primary: true)]
private Snowflake $id;
}
```

### Twitter
Snowflake identifier for Twitter (X), beginning from `2010-11-04`. Can incorporate a machine ID to generate distinct Snowflakes. Default values for `machineId` can be defined globally via the `\Cycle\ORM\Entity\Behavior\Identifier\Listener\SnowflakeTwitter::setDefaults()` method.

```php
use Cycle\Annotated\Annotation\Column;
use Cycle\Annotated\Annotation\Entity;
use Cycle\ORM\Entity\Behavior\Identifier;
use Ramsey\Identifier\Snowflake;

#[Entity]
#[Identifier\SnowflakeTwitter(field: 'id', machineId: 30)]
class User
{
#[Column(type: 'snowflake', primary: true)]
private Snowflake $id;
}
```

## ULID Examples

**ULID (Universally Unique Lexicographically Sortable Identifier):** A 128-bit identifier designed for high uniqueness and lexicographical sortability. It combines a timestamp component with random data, allowing for ordered IDs that can be generated rapidly and are human-readable, making it ideal for databases and distributed systems.
### ULID (Universally Unique Lexicographically Sortable Identifier)
A 128-bit identifier designed for high uniqueness and lexicographical sortability. It combines a timestamp component with random data, allowing for ordered IDs that can be generated rapidly and are human-readable, making it ideal for databases and distributed systems.

```php
use Cycle\Annotated\Annotation\Column;
Expand All @@ -44,7 +130,8 @@ class User

## UUID Examples

**UUID Version 1 (Time-based):** Generated using the current timestamp and the MAC address of the computer, ensuring unique identification based on time and hardware.
### UUID Version 1 (Time-based)
Generated using the current timestamp and the MAC address of the computer, ensuring unique identification based on time and hardware. Default values for `node` and `clockSeq` can be defined globally via the `\Cycle\ORM\Entity\Behavior\Identifier\Listener\Uuid1::setDefaults()` method.

```php
use Cycle\Annotated\Annotation\Column;
Expand All @@ -61,7 +148,8 @@ class User
}
```

**UUID Version 2 (DCE Security):** Similar to version 1 but includes a local identifier such as a user ID or group ID, primarily used in DCE security contexts.
### UUID Version 2 (DCE Security)
Similar to version 1 but includes a local identifier such as a user ID or group ID, primarily used in DCE security contexts. Default values for `localDomain`, `localIdentifier`, `node` and `clockSeq` can be defined globally via the `\Cycle\ORM\Entity\Behavior\Identifier\Listener\Uuid2::setDefaults()` method.

```php
use Cycle\Annotated\Annotation\Column;
Expand All @@ -78,7 +166,8 @@ class User
}
```

**UUID Version 3 (Name-based, MD5):** Created by hashing a namespace identifier and name using MD5, resulting in a deterministic UUID based on input data.
### UUID Version 3 (Name-based, MD5)
Created by hashing a namespace identifier and name using MD5, resulting in a deterministic UUID based on input data.

```php
use Cycle\Annotated\Annotation\Column;
Expand All @@ -99,7 +188,8 @@ class User
}
```

**UUID Version 4 (Random):** Generated entirely from random or pseudo-random numbers, offering high unpredictability and uniqueness.
### UUID Version 4 (Random)
Generated entirely from random or pseudo-random numbers, offering high unpredictability and uniqueness.

```php
use Cycle\Annotated\Annotation\Column;
Expand All @@ -116,7 +206,8 @@ class User
}
```

**UUID Version 5 (Name-based, SHA-1):** Similar to version 3 but uses SHA-1 hashing, providing a different deterministic UUID based on namespace and name.
### UUID Version 5 (Name-based, SHA-1)
Similar to version 3 but uses SHA-1 hashing, providing a different deterministic UUID based on namespace and name.

```php
use Cycle\Annotated\Annotation\Column;
Expand All @@ -137,7 +228,8 @@ class User
}
```

**UUID Version 6 (Draft/Upcoming):** An experimental or proposed version focused on improving time-based UUIDs with more sortable properties (not yet widely adopted).
### UUID Version 6 (Draft/Upcoming)
An experimental or proposed version focused on improving time-based UUIDs with more sortable properties (not yet widely adopted). Default values for `node` and `clockSeq` can be defined globally via the `\Cycle\ORM\Entity\Behavior\Identifier\Listener\Uuid6::setDefaults()` method.

```php
use Cycle\Annotated\Annotation\Column;
Expand All @@ -154,7 +246,8 @@ class User
}
```

**UUID Version 7 (Draft/Upcoming):** A newer proposal designed to incorporate sortable features based on Unix timestamp, enhancing performance in database indexing.
### UUID Version 7 (Draft/Upcoming)
A newer proposal designed to incorporate sortable features based on Unix timestamp, enhancing performance in database indexing.

```php
use Cycle\Annotated\Annotation\Column;
Expand All @@ -171,7 +264,33 @@ class User
}
```

You can find more information about Entity behavior UUID [here](https://cycle-orm.dev/docs/entity-behaviors-identifier).
## Global Configuration

Some listener classes provide static functions allowing you to define global default values for various attributes. This approach helps you to:

* Initialize defaults at a suitable point in your application's lifecycle.
* Customize defaults dynamically based on environment-specific conditions.
* Minimize redundancy by setting shared attribute values once, instead of repeatedly specifying them across entities.

**Sample code:**

```php
use Cycle\ORM\Entity\Behavior\Identifier\Listener;

Listener\SnowflakeGeneric::setDefaults($node, $epochOffset);
Listener\SnowflakeDiscord::setDefaults($workerId, $processId);
Listener\SnowflakeInstagram::setDefaults($shardId);
Listener\SnowflakeMastodon::setDefaults($tableName);
Listener\SnowflakeTwitter::setDefaults($machineId);

Listener\Uuid1::setDefaults($node, $clockSeq);
Listener\Uuid2::setDefaults($localDomain, $localIdentifier, $node, $clockSeq);
Listener\Uuid3::setDefaults($namespace, $name);
Listener\Uuid5::setDefaults($namespace, $name);
Listener\Uuid6::setDefaults($node, $clockSeq);
````

You can find more information about Entity behavior Identifier [here](https://cycle-orm.dev/docs/entity-behaviors-identifier).

## License:

Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
},
"require": {
"php": ">=8.2",
"cycle/entity-behavior": "^1.6",
"cycle/entity-behavior": "^1.7",
"ramsey/identifier": "^0.1"
},
"require-dev": {
Expand Down
Loading
Loading