PHPackages                             azaharizaman/nexus-common - 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. azaharizaman/nexus-common

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

azaharizaman/nexus-common
=========================

Shared domain primitives, contracts, and value objects for Nexus packages

v0.1.0-alpha1(1mo ago)0320MITHTMLPHP ^8.3

Since May 5Pushed 1mo agoCompare

[ Source](https://github.com/azaharizaman/nexus-common)[ Packagist](https://packagist.org/packages/azaharizaman/nexus-common)[ RSS](/packages/azaharizaman-nexus-common/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (4)Versions (2)Used By (20)

Nexus Common
============

[](#nexus-common)

**Shared domain primitives, contracts, and value objects for Nexus packages.**

The Common package contains foundational elements that are shared across multiple Nexus packages, ensuring consistent domain modeling and reducing code duplication.

Overview
--------

[](#overview)

This package provides:

- **Value Objects**: Immutable domain primitives (TenantId, etc.)
- **Contracts**: Common interfaces used across packages (ClockInterface, behavioral contracts)
- **PSR Compliance**: Uses PSR-14 `Psr\EventDispatcher\EventDispatcherInterface` for event dispatching
- **Exceptions**: Shared domain exceptions

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

[](#installation)

```
composer require azaharizaman/nexus-common
```

Package Contents
----------------

[](#package-contents)

### Value Objects (`src/ValueObjects/`)

[](#value-objects-srcvalueobjects)

#### Core Value Objects

[](#core-value-objects)

Value ObjectInterfacesDescription`TenantId`Comparable, SerializableVOStrongly-typed tenant identifier (ULID)`Money`Comparable, Addable, Subtractable, Multipliable, Divisible, CurrencyConvertible, SerializableVO, FormattableImmutable monetary value with precision arithmetic`Percentage`Comparable, Addable, Subtractable, Multipliable, Divisible, SerializableVO, FormattablePercentage values (0-100) for taxes, discounts, variance#### Measurement Value Objects

[](#measurement-value-objects)

Value ObjectInterfacesDescription`UnitOfMeasurement`Enumable, SerializableVOStandard measurement units (kg, m, L, pcs, etc.)`Measurement`Comparable, Addable, Subtractable, Multipliable, Divisible, Convertible, SerializableVO, FormattableMeasurements with unit conversion`Quantity`Comparable, Addable, Subtractable, Multipliable, Divisible, Convertible, SerializableVODiscrete quantities with units#### Identifier Value Objects

[](#identifier-value-objects)

Value ObjectInterfacesDescription`EntityId`Comparable, SerializableVOBase class for strongly-typed ULID identifiers`CustomerId`Comparable, SerializableVOCustomer identifier`ProductId`Comparable, SerializableVOProduct identifier`EmployeeId`Comparable, SerializableVOEmployee identifier`VendorId`Comparable, SerializableVOVendor identifier`WarehouseId`Comparable, SerializableVOWarehouse identifier#### Contact Information Value Objects

[](#contact-information-value-objects)

Value ObjectInterfacesDescription`Email`Comparable, SerializableVOValidated email address with domain extraction`PhoneNumber`Comparable, SerializableVOInternational phone number (E.164 format)`Address`Comparable, SerializableVOPhysical address with country validation#### Temporal Value Objects

[](#temporal-value-objects)

Value ObjectInterfacesDescription`DateRange`Comparable, Temporal, AdjustableTime, SerializableVODate period with overlap detection`AuditMetadata`Auditable, SerializableVOCreated/updated by and timestamps#### Financial Value Objects

[](#financial-value-objects)

Value ObjectInterfacesDescription`TaxRate`Comparable, Multipliable, SerializableVOTax rate with jurisdiction and effectivity`TaxCode`Comparable, Multipliable, SerializableVOTax code with rate and description#### State Management Value Objects

[](#state-management-value-objects)

Value ObjectInterfacesDescription`Status`Stateful, Enumable, SerializableVOState machine with transition validation#### Advanced Analysis Value Objects

[](#advanced-analysis-value-objects)

Value ObjectInterfacesDescription`VarianceResult`Comparable, Addable, Subtractable, Multipliable, Divisible, Statistical, TrendAnalyzable, SerializableVOBudget variance with statistical and trend analysis#### Metadata Value Objects

[](#metadata-value-objects)

Value ObjectInterfacesDescription`AttachmentMetadata`SerializableVOFile metadata for document attachments### Behavioral Interfaces (`src/Contracts/`)

[](#behavioral-interfaces-srccontracts)

#### Arithmetic Interfaces

[](#arithmetic-interfaces)

InterfaceMethodsDescription`Addable``add(self $other): static`Addition capability`Subtractable``subtract(self $other): static`Subtraction capability`Multipliable``multiply(float|int $multiplier): static`Multiplication by scalar`Divisible``divide(float|int $divisor): static`Division by scalar#### Comparison Interface

[](#comparison-interface)

InterfaceMethodsDescription`Comparable``compareTo()`, `equals()`, `greaterThan()`, `lessThan()`Comparison capability#### Conversion Interfaces

[](#conversion-interfaces)

InterfaceMethodsDescription`Convertible``convertTo(string $toUnit)`, `canConvertTo(string $toUnit)`Unit conversion capability`CurrencyConvertible``convertToCurrency()`, `getCurrency()`Currency conversion capability#### Serialization Interfaces

[](#serialization-interfaces)

InterfaceMethodsDescription`SerializableVO``toArray()`, `toString()`, `fromArray()`Serialization capability`Formattable``format(array $options = [])`Custom formatting capability#### State/Enum Interfaces

[](#stateenum-interfaces)

InterfaceMethodsDescription`Enumable``values()`, `getValue()`, `isValid()`Enumeration capability`Stateful``getState()`, `canTransitionTo()`, `isFinal()`State machine capability#### Time Interfaces

[](#time-interfaces)

InterfaceMethodsDescription`Temporal``getStartDate()`, `getEndDate()`, `contains()`, `overlaps()`Temporal period capability`AdjustableTime``shift()`, `extend()`Time adjustment capability#### Analysis Interfaces

[](#analysis-interfaces)

InterfaceMethodsDescription`Auditable``getCreatedBy()`, `getCreatedAt()`, `getUpdatedBy()`, `getUpdatedAt()`Audit trail capability`Statistical``average()`, `abs()`, `isWithinRange()`Statistical analysis capability`TrendAnalyzable``getTrendDirection()`, `percentageChange()`, `isSignificantChange()`Trend analysis capability#### System Interfaces

[](#system-interfaces)

InterfaceMethodsDescription`ClockInterface``now()`Provides current time for testability`UlidInterface``generate()`, `isValid()`, `getTimestamp()`ULID generation for entity identifiers> **Note:** For event dispatching, use PSR-14's `Psr\EventDispatcher\EventDispatcherInterface` directly. This package depends on `psr/event-dispatcher`.

### Exceptions (`src/Exceptions/`)

[](#exceptions-srcexceptions)

ExceptionDescription`InvalidValueException`Base exception for invalid value objects`InvalidMoneyException`Exception for invalid Money operations`CurrencyMismatchException`Exception when currencies don't match in operationsUsage Examples
--------------

[](#usage-examples)

### Money Value Object

[](#money-value-object)

The `Money` value object provides immutable monetary value representation with precision arithmetic.

**Important - Money vs Currency Package Boundary:**

- **`Money` (this package)**: Arithmetic operations, comparison, formatting, allocation
- **`Nexus\Currency` package**: Exchange rate management, cross-currency conversions with rates

Use `Money` for calculations within a single currency. Use `Nexus\Currency` when you need exchange rates and cross-currency operations.

```
use Nexus\Common\ValueObjects\Money;

// Create money instances
$price = Money::of(10000, 'MYR');  // RM 100.00 (10000 minor units)
$tax = Money::of(600, 'MYR');      // RM 6.00

// Arithmetic operations (immutable - returns new instances)
$total = $price->add($tax);        // RM 106.00
$discount = $price->multiply(0.1); // RM 10.00
$final = $total->subtract($discount);

// Comparison
if ($total->greaterThan($price)) {
    echo "Total exceeds price";
}

// Low-level currency conversion (with known exchange rate)
// For exchange rate management, use Nexus\Currency package
$usd = $price->convertToCurrency('USD', exchangeRate: 4.5);

// Formatting
echo $price->format(['decimals' => 2, 'symbol' => true]); // "MYR 100.00"

// Serialization
$data = $price->toArray();
// ['amountInMinorUnits' => 10000, 'amount' => 10000, 'currency' => 'MYR']
$restored = Money::fromArray($data);

// State checks
if ($money->isZero()) { /* ... */ }
if ($money->isPositive()) { /* ... */ }

// Allocate by ratios
$shares = Money::of(10000, 'MYR')->allocate([60, 30, 10]);
// Returns: [6000, 3000, 1000] minor units
```

### Percentage Value Object

[](#percentage-value-object)

```
use Nexus\Common\ValueObjects\Percentage;

// Create percentage
$taxRate = Percentage::of(6.0);              // 6%
$discount = Percentage::fromDecimal(0.15);   // 15%

// Calculate percentage of amount
$taxAmount = $taxRate->of(1000.0);   // 60.0

// Arithmetic
$totalRate = $taxRate->add(Percentage::of(2.0)); // 8%
$halfRate = $taxRate->divide(2);                 // 3%

// Conversion
$decimal = $taxRate->asDecimal();    // 0.06

// Formatting
echo $taxRate->format(['decimals' => 2]); // "6.00%"
```

### Measurement and Quantity

[](#measurement-and-quantity)

```
use Nexus\Common\ValueObjects\Measurement;
use Nexus\Common\ValueObjects\Quantity;
use Nexus\Common\ValueObjects\UnitOfMeasurement;

// Measurement with conversions
$weight = Measurement::of(2.5, UnitOfMeasurement::KG);
$weightInGrams = $weight->convertTo(UnitOfMeasurement::G);   // 2500 g
$weightInPounds = $weight->convertTo(UnitOfMeasurement::LB); // ~5.51 lb

// Arithmetic with auto-conversion
$weight1 = Measurement::of(1000, UnitOfMeasurement::G);
$weight2 = Measurement::of(1, UnitOfMeasurement::KG);
$total = $weight1->add($weight2); // 2000 g (auto-converts to common unit)

// Check conversion compatibility
if ($weight->canConvertTo(UnitOfMeasurement::G)) {
    $converted = $weight->convertTo(UnitOfMeasurement::G);
}

// Quantity for inventory
$stock = Quantity::of(100, UnitOfMeasurement::PCS);
$shipped = Quantity::of(25, UnitOfMeasurement::PCS);
$remaining = $stock->subtract($shipped); // 75 pcs

if ($remaining->isZero()) {
    echo "Out of stock";
}
```

### Entity Identifiers

[](#entity-identifiers)

```
use Nexus\Common\ValueObjects\CustomerId;
use Nexus\Common\ValueObjects\ProductId;

// Generate new IDs (ULID-based)
$customerId = CustomerId::generate();
$productId = ProductId::generate();

// Type safety prevents mixing
function processOrder(CustomerId $customerId, ProductId $productId) {
    // Can't accidentally pass ProductId where CustomerId is expected
    // PHP type system enforces this at compile time
}

// From string (e.g., from database)
$id = CustomerId::fromString('01HN6Z8Y9C3EXAMPLE123');

// Serialization
$idString = $customerId->toString();
$ulid = $customerId->toUlid(); // Returns Symfony\Component\Uid\Ulid

// Comparison
if ($customerId->equals($otherCustomerId)) {
    echo "Same customer";
}
```

### Contact Information

[](#contact-information)

```
use Nexus\Common\ValueObjects\Email;
use Nexus\Common\ValueObjects\PhoneNumber;
use Nexus\Common\ValueObjects\Address;

// Email validation (RFC 5322)
try {
    $email = Email::of('customer@example.com');
    $domain = $email->getDomain();      // "example.com"
    $local = $email->getLocalPart();    // "customer"
} catch (InvalidValueException $e) {
    // Invalid email format
}

// Phone number formatting (E.164)
$phone = PhoneNumber::of('+60123456789');
$countryCode = $phone->getCountryCode();  // "+60"
$formatted = $phone->format();             // "+60 12-345 6789"

// Address with ISO country codes
$address = Address::of(
    street: '123 Main Street',
    street2: 'Suite 100',
    city: 'Kuala Lumpur',
    state: 'Federal Territory',
    postalCode: '50000',
    country: 'MY'  // ISO 3166-1 alpha-2
);
$full = $address->getFullAddress(); // Complete formatted address
```

### DateRange and Temporal Operations

[](#daterange-and-temporal-operations)

```
use Nexus\Common\ValueObjects\DateRange;

// Create date range
$fiscalPeriod = DateRange::of(
    startDate: new DateTimeImmutable('2024-01-01'),
    endDate: new DateTimeImmutable('2024-12-31')
);

// Check if date is within range
$isInPeriod = $fiscalPeriod->contains(
    new DateTimeImmutable('2024-06-15')
); // true

// Check overlaps
$q1 = DateRange::of(
    new DateTimeImmutable('2024-01-01'),
    new DateTimeImmutable('2024-03-31')
);
$overlaps = $fiscalPeriod->overlaps($q1); // true

// Time adjustments
$extended = $fiscalPeriod->extend(days: 30);   // Extends end date
$shifted = $fiscalPeriod->shift(months: 1);    // Shifts both dates

// Get duration
$days = $fiscalPeriod->getDays(); // 366 (2024 is leap year)

// Check if currently active
if ($fiscalPeriod->isActive()) {
    echo "Period is active";
}
```

### Tax Calculation

[](#tax-calculation)

```
use Nexus\Common\ValueObjects\TaxRate;
use Nexus\Common\ValueObjects\TaxCode;
use Nexus\Common\ValueObjects\Percentage;

// Tax rate with temporal validity
$taxRate = TaxRate::of(
    rate: Percentage::of(6.0),
    taxType: 'SST',
    jurisdiction: 'MY',
    effectiveFrom: new DateTimeImmutable('2024-01-01'),
    effectiveTo: new DateTimeImmutable('2024-12-31')
);

// Check if rate is valid on specific date
$date = new DateTimeImmutable('2024-06-15');
if ($taxRate->isEffectiveOn($date)) {
    $taxAmount = $taxRate->calculateTax(amountInMinorUnits: 100000);
    // RM 1000 -> RM 60 tax
}

// Tax code system
$taxCode = TaxCode::of(
    code: 'TX',
    description: 'Standard Rate',
    rate: Percentage::of(6.0),
    isActive: true
);

if ($taxCode->isActive()) {
    $tax = $taxCode->calculateTax(amountInMinorUnits: 50000);
    // RM 500 -> RM 30 tax
}
```

### Status State Machine

[](#status-state-machine)

```
use Nexus\Common\ValueObjects\Status;

// Factory methods for common states
$draft = Status::draft();
$pending = Status::pending();
$approved = Status::approved();
$rejected = Status::rejected();
$closed = Status::closed();

// Check allowed transitions
if ($draft->canTransitionTo($pending)) {
    $newStatus = $draft->transitionTo($pending);
    echo $newStatus->getState(); // "pending"
}

// Prevent invalid transitions
try {
    $draft->transitionTo($approved); // Draft -> Approved not allowed
} catch (InvalidValueException $e) {
    echo "Invalid state transition";
}

// Check if final state
if ($approved->isFinal()) {
    echo "No further transitions allowed";
}

// Custom workflow
$customStatus = Status::of(
    state: 'in_review',
    allowedTransitions: ['approved', 'rejected'],
    isFinal: false
);
```

### Variance Analysis (Advanced)

[](#variance-analysis-advanced)

```
use Nexus\Common\ValueObjects\VarianceResult;

// Create variance result
$result = VarianceResult::of(
    actual: 95000.0,
    budget: 100000.0
);

// Get variance (computed property)
$variance = $result->getVariance();           // -5000.0
$percentage = $result->getPercentageVariance(); // -5.0%

// Business analysis
if ($result->isUnfavorable()) {
    echo "Actual is below budget (unfavorable)";
}
if ($result->isFavorable()) {
    echo "Actual exceeds budget (favorable)";
}

// Statistical operations
$results = [
    VarianceResult::of(95000, 100000),
    VarianceResult::of(105000, 100000),
    VarianceResult::of(98000, 100000),
];
$average = VarianceResult::average($results);

// Trend analysis
$lastMonth = VarianceResult::of(90000, 100000);
$thisMonth = VarianceResult::of(95000, 100000);

$trend = $thisMonth->getTrendDirection($lastMonth); // 'up'
$change = $thisMonth->percentageChange($lastMonth); // 5.56%

if ($thisMonth->isSignificantChange($lastMonth, threshold: 0.10)) {
    echo "Significant variance change detected (>10%)";
}

// Range validation
$minResult = VarianceResult::of(80000, 100000);
$maxResult = VarianceResult::of(120000, 100000);
if ($result->isWithinRange($minResult, $maxResult)) {
    echo "Result is within acceptable range";
}

// Arithmetic operations
$combined = $result->add($lastMonth); // Combines actual and budget
$adjusted = $result->multiply(1.1);   // Scale by 110%
```

### Audit Metadata

[](#audit-metadata)

```
use Nexus\Common\ValueObjects\AuditMetadata;

// Create audit metadata for new entity
$audit = AuditMetadata::forCreate(userId: 'user-123');

// Update metadata when entity is modified
$updatedAudit = $audit->withUpdate(userId: 'user-456');

// Access audit information
$createdBy = $audit->getCreatedBy();            // 'user-123'
$createdAt = $audit->getCreatedAt();            // DateTimeImmutable
$updatedBy = $updatedAudit->getUpdatedBy();     // 'user-456'
$updatedAt = $updatedAudit->getUpdatedAt();     // DateTimeImmutable

// Serialization for storage
$data = $audit->toArray();
/*
[
    'created_by' => 'user-123',
    'created_at' => '2024-01-15T10:30:00+00:00',
    'updated_by' => null,
    'updated_at' => null,
]
*/

$restored = AuditMetadata::fromArray($data);
```

### Attachment Metadata

[](#attachment-metadata)

```
use Nexus\Common\ValueObjects\AttachmentMetadata;

// Track file attachment
$attachment = AttachmentMetadata::of(
    fileName: 'invoice_2024_001.pdf',
    mimeType: 'application/pdf',
    sizeInBytes: 524288,  // 512 KB
    uploadedAt: new DateTimeImmutable(),
    uploadedBy: 'user-123',
    storagePath: 'invoices/2024/01/invoice_2024_001.pdf'
);

// Get file information
$extension = $attachment->getFileExtension();     // 'pdf'
$humanSize = $attachment->getHumanReadableSize(); // '512.00 KB'

// Serialization for database storage
$data = $attachment->toArray();
$restored = AttachmentMetadata::fromArray($data);
```

### TenantId

[](#tenantid)

```
use Nexus\Common\ValueObjects\TenantId;

// Create a new TenantId
$tenantId = TenantId::generate();

// Create from existing ULID string
$tenantId = TenantId::fromString('01ARZ3NDEKTSV4RRFFQ69G5FAV');

// Compare tenant IDs
if ($tenantId->equals($otherTenantId)) {
    echo "Same tenant";
}

// Get string value
$tenantIdString = $tenantId->toString();
```

### ClockInterface (System Interface)

[](#clockinterface-system-interface)

```
use Nexus\Common\Contracts\ClockInterface;

final readonly class MyService
{
    public function __construct(
        private ClockInterface $clock
    ) {}

    public function isExpired(\DateTimeImmutable $expiresAt): bool
    {
        return $expiresAt < $this->clock->now();
    }
}
```

### Logging (PSR-3)

[](#logging-psr-3)

```
use Psr\Log\LoggerInterface;

final readonly class MyService
{
    public function __construct(
        private LoggerInterface $logger
    ) {}

    public function doSomething(): void
    {
        $this->logger->info('Operation completed', [
            'context' => 'additional data'
        ]);
    }
}
```

Design Principles
-----------------

[](#design-principles)

### 1. Immutability

[](#1-immutability)

All value objects are immutable (`readonly` classes). Operations return new instances:

```
$money = Money::of(100, 'MYR');
$newMoney = $money->add(Money::of(50, 'MYR')); // Returns new instance
// $money still contains 100, $newMoney contains 150
```

### 2. Type Safety

[](#2-type-safety)

Strong typing with PHP 8.3+ features:

- `declare(strict_types=1)` in all files
- Readonly properties
- Native enums where appropriate
- Interface-based polymorphism

```
// Type system prevents mixing different entity IDs
function processOrder(CustomerId $customerId, ProductId $productId) {
    // Can't pass ProductId where CustomerId is expected
}
```

### 3. Validation

[](#3-validation)

Invalid states are impossible to create:

```
// Throws InvalidValueException immediately
$email = Email::of('invalid-email'); // Exception!
$percentage = Percentage::of(150.0); // Exception! (must be 0-100)
```

### 4. Interface Segregation Principle (ISP)

[](#4-interface-segregation-principle-isp)

Small, focused interfaces that can be composed:

```
// Money implements 8 focused interfaces
class Money implements
    Comparable,           // Comparison operations
    Addable,              // Addition
    Subtractable,         // Subtraction
    Multipliable,         // Multiplication
    Divisible,            // Division
    CurrencyConvertible,  // Currency operations
    SerializableVO,       // Serialization
    Formattable           // Formatting
{
    // Each interface adds specific capability
}
```

### 5. Framework Agnostic

[](#5-framework-agnostic)

No framework dependencies - works with any PHP framework:

- Laravel
- Symfony
- Slim
- Pure PHP

### 6. Interface Composition Patterns

[](#6-interface-composition-patterns)

**Arithmetic Group** (Addable + Subtractable + Multipliable + Divisible):

- `Money`, `Percentage`, `Measurement`, `Quantity`, `VarianceResult`

**Comparison + Serialization** (Comparable + SerializableVO):

- `Email`, `PhoneNumber`, `Address`, `EntityId` and subclasses

**Temporal Group** (Temporal + AdjustableTime):

- `DateRange`

**State Management** (Stateful + Enumable):

- `Status`

**Analysis Group** (Statistical + TrendAnalyzable):

- `VarianceResult`

**Conversion Capabilities**:

- `Convertible` - Unit conversion (Measurement, Quantity)
- `CurrencyConvertible` - Currency conversion (Money)

### 7. Behavior Contracts, Not Markers

[](#7-behavior-contracts-not-markers)

Interfaces define actual capabilities with methods, not just markers:

```
// ✅ GOOD: Defines behavior
interface Addable {
    public function add(self $other): static;
}

// ❌ BAD: Just a marker (not used in this package)
interface ValueObjectInterface {
    // No methods - just marks a class
}
```

Dependencies
------------

[](#dependencies)

- **PHP** ^8.3
- **psr/log** ^3.0 (PSR-3 Logger Interface)
- **symfony/uid** ^7.0 (ULID generation for identifiers)

All dependencies are minimal and framework-agnostic.

License
-------

[](#license)

MIT License - see LICENSE file for details.

---

**Part of the Nexus Package Monorepo**

###  Health Score

37

—

LowBetter than 81% of packages

Maintenance93

Actively maintained with recent releases

Popularity4

Limited adoption so far

Community15

Small or concentrated contributor base

Maturity34

Early-stage or recently created project

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

Unknown

Total

1

Last Release

36d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/117408?v=4)[Azahari Zaman](/maintainers/azaharizaman)[@azaharizaman](https://github.com/azaharizaman)

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/azaharizaman-nexus-common/health.svg)

```
[![Health](https://phpackages.com/badges/azaharizaman-nexus-common/health.svg)](https://phpackages.com/packages/azaharizaman-nexus-common)
```

###  Alternatives

[symfony/symfony

The Symfony PHP framework

31.4k86.9M2.2k](/packages/symfony-symfony)[web-auth/webauthn-lib

FIDO2/Webauthn Support For PHP

1237.8M117](/packages/web-auth-webauthn-lib)[web-auth/webauthn-framework

FIDO2/Webauthn library for PHP and Symfony Bundle.

51090.8k2](/packages/web-auth-webauthn-framework)[phpro/soap-client

A general purpose SoapClient library

8955.9M52](/packages/phpro-soap-client)[ecotone/ecotone

Enterprise architecture layer for Laravel and Symfony — CQRS, Event Sourcing, Durable Workflows (Sagas, Orchestrators), Projections, and Outbox messaging via PHP attributes.

562565.8k41](/packages/ecotone-ecotone)[tempest/framework

The PHP framework that gets out of your way.

2.2k31.1k11](/packages/tempest-framework)

PHPackages © 2026

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