PHPackages                             andreaskasper/phlibs - 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. andreaskasper/phlibs

ActiveLibrary

andreaskasper/phlibs
====================

A lightweight PHP utility library: MySQL/PDO database wrappers, HTTP caching, web content caching, string helpers.

v0.1(8y ago)026FreeFoodLicensePHPPHP &gt;=5.4.0CI failing

Since Nov 14Pushed 1mo ago1 watchersCompare

[ Source](https://github.com/andreaskasper/phlibs)[ Packagist](https://packagist.org/packages/andreaskasper/phlibs)[ RSS](/packages/andreaskasper-phlibs/feed)WikiDiscussions master Synced 4d ago

READMEChangelog (1)Dependencies (7)Versions (2)Used By (0)

📚 phlibs — PHP Class Library
============================

[](#-phlibs--php-class-library)

A lightweight PHP utility library extracted from the ASICMS framework. Provides database abstraction (MySQL/MariaDB via MySQLi and PDO), monetary value objects with live exchange rates, HTTP page caching, web content caching, and string helpers.

[![PHP Version](https://camo.githubusercontent.com/6eff5053a32c9e0bcc0982c4f118ef689cad7831a3d982767aae3901bf67313c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d253345253344372e342d626c75652e737667)](https://php.net)[![License](https://camo.githubusercontent.com/57f94a7ed5ab851435c22fc1d2aca2c9976203b9f485d31084fd63ac6fc3d5fb/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d46726565466f6f644c6963656e73652d677265656e2e737667)](https://packagist.org/packages/andreaskasper/phlibs)[![Latest Stable Version](https://camo.githubusercontent.com/4d621f7acd3f41ca24c35d2111cafd95bdd6363fe23034a93ed351876ca0e51e/68747470733a2f2f706f7365722e707567782e6f72672f616e64726561736b61737065722f70686c6962732f762f737461626c652e737667)](https://packagist.org/packages/andreaskasper/phlibs)[![Total Downloads](https://camo.githubusercontent.com/61887919c7057c10dcaf0052a82b1ba35a0f6ad41a265bfa1a5d6b4c804fb21b/68747470733a2f2f706f7365722e707567782e6f72672f616e64726561736b61737065722f70686c6962732f646f776e6c6f616473)](https://packagist.org/packages/andreaskasper/phlibs)[![GitHub Issues](https://camo.githubusercontent.com/203a68eb7c0dc9b4128a5e325b15c6b83a45d2cba5531f8255b8d336b93e9055/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6973737565732f616e64726561736b61737065722f70686c6962732e737667)](https://github.com/andreaskasper/phlibs/issues)

---

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

[](#installation)

```
composer require andreaskasper/phlibs
```

Or add to your `composer.json`:

```
{
    "require": {
        "andreaskasper/phlibs": "*"
    }
}
```

---

Classes
-------

[](#classes)

### SQL — MySQLi Database Wrapper

[](#sql--mysqli-database-wrapper)

Full-featured MySQLi wrapper with connection pooling, query history, placeholder-based escaping (`{0}`, `{1}`, …), and convenience methods for common operations.

```
use phlibs\SQL;

// Initialize connection via URI
SQL::init(0, "mysql://user:password@localhost:3306/mydb/");

$db = new SQL(0);

// Query with placeholder escaping
$rows = $db->cmdrows('SELECT * FROM users WHERE status = "{0}"', ['active']);
$row  = $db->cmdrow('SELECT * FROM users WHERE id = "{0}"', [42]);
$count = $db->cmdvalue('SELECT COUNT(*) FROM users');

// Insert / Upsert
$db->Create('users', ['name' => 'Alice', 'email' => 'alice@example.com']);
$db->CreateUpdate('users', ['id' => 1, 'name' => 'Alice', 'visits' => 5]);

// Bulk upsert
$db->CreateUpdateArray('users', [
    ['id' => 1, 'name' => 'Alice'],
    ['id' => 2, 'name' => 'Bob'],
]);

// Update with WHERE keys
$db->Update('users', ['id' => 1, 'name' => 'Updated'], ['id']);

// Long query monitoring
SQL::setLongQueryCallback(5, function($info) {
    error_log('Slow query: ' . $info['query'] . ' (' . $info['dauer'] . 's)');
});
```

**Features:**

- Connection URI parsing (`mysql://user:pass@host:port/database/prefix`)
- Automatic connection retry (50 attempts, 500ms interval)
- `{n}` placeholder escaping via `real_escape_string`
- Query counter, timer, and history (last 100 queries)
- Long-running query callback
- Multi-query support (`multicmd`)
- `max_allowed_packet()` helper
- Magic properties: `$db->lastcmd`, `$db->insertid`, `$db->counter`, `$db->error`, `$db->success`

---

### DB — PDO Database Wrapper

[](#db--pdo-database-wrapper)

Lightweight PDO wrapper with the same `cmd` / `cmdrow` / `cmdrows` / `cmdvalue` API as the SQL class. Supports any PDO-compatible database (MySQL, PostgreSQL, SQLite, …).

```
use phlibs\DB;

DB::init(0, 'mysql:host=localhost;dbname=mydb', 'user', 'password');

$db = new DB(0);
$row = $db->cmdrow('SELECT * FROM users WHERE id = {0}', [42]);
```

---

### Money — Immutable Monetary Value Object

[](#money--immutable-monetary-value-object)

Represents monetary amounts with currency awareness. Fully immutable — all arithmetic operations return new instances. Supports locale-aware formatting, live exchange rates, and pluggable rate providers.

```
use phlibs\Money;

// Create
$price = new Money(19.99, 'EUR');
$price = Money::EUR(19.99);                         // Static factory
$price = Money::fromString('EUR', '1.234,56');       // German format

// Arithmetic (all return new instances)
$total    = $price->add(5.00);                       // 24.99 EUR
$diff     = $price->subtract(Money::EUR(10));         // 9.99 EUR
$doubled  = $price->multiply(2);                      // 39.98 EUR
$split    = $price->divide(3);                        // 6.66 EUR
$absolute = $price->negate()->abs();                  // 19.99 EUR

// Formatting
echo $price->format('de');     // "19,99€"
echo $price->format('en');     // "19.99€"
echo Money::USD(42)->format(); // "$42.00"
echo (string) $price;          // Uses default locale

// Properties
$price->amount;    // 19.99
$price->currency;  // 'EUR'
$price->symbol;    // '€'
$price->name;      // 'Euro'

// Comparisons
$price->isPositive();              // true
$price->isZero();                  // false
$price->equals(Money::EUR(19.99)); // true
$price->compareTo($other);        // -1, 0, or 1
```

#### Live Exchange Rates

[](#live-exchange-rates)

Fetch real-time exchange rates from the [Frankfurter API](https://frankfurter.app) (ECB data, free, no API key):

```
// Enable live exchange rates (one-time setup)
Money::enableLiveExchange();

// Convert with auto-fetched rates (cached for 1 hour)
$eur = Money::EUR(100);
$usd = $eur->exchangeTo('USD');   // Fetches live EUR→USD rate
$gbp = $eur->exchangeTo('GBP');   // Same API call, rate already cached

// Check the rate directly
$rate = Money::exchangeRate('EUR', 'USD'); // e.g. 1.0847

// Custom configuration
Money::enableLiveExchange(
    enabled: true,
    apiUrl:  'https://api.frankfurter.dev',  // or your own API
    ttl:     7200,                            // Cache for 2 hours
    timeout: 3                                // 3s HTTP timeout
);

// Prefetch rates to warm the cache
Money::prefetchRates(['EUR', 'USD', 'GBP']);

// Debug cache state
$info = Money::getExchangeCacheInfo();
// ['EUR' => ['rates' => [...], 'fetched_at' => 1719..., 'age_seconds' => 42]]

// Force refresh
Money::clearExchangeCache();
```

The lookup order is: custom provider → live API → hardcoded fallback. You can also combine a custom provider with live rates:

```
// Custom provider for special rates, live API as fallback
Money::setExchangeRateProvider(function($from, $to) {
    if ($from === 'EUR' && $to === 'SPECIAL') return 42.0;
    return null; // Fall through to live API
});
Money::enableLiveExchange();
```

**Features:**

- Immutable value object pattern
- Static factory methods (`Money::EUR(amount)`, `Money::USD(amount)`, …)
- Locale-aware formatting (German, English, European conventions)
- Zero-decimal currencies (HUF, JPY, CZK) and 3-decimal (KWD, BHD, OMR)
- Symbol placement (before for USD/GBP, after for EUR/CHF)
- Live exchange rates via frankfurter.app (ECB data, free, no API key)
- In-memory rate cache with configurable TTL
- Cache prefetching for batch conversions
- Pluggable exchange rate provider
- Comparison methods (`equals`, `compareTo`, `isZero`, `isPositive`, `isNegative`)
- `toArray()` and `jsonSerialize()` for serialization

---

### Currency — Currency Value Object

[](#currency--currency-value-object)

Represents an ISO 4217 currency with its metadata. Acts as the single source of truth for symbols, names, decimal behavior, and symbol placement across the library. Covers 115+ currencies.

```
use phlibs\Currency;

// Create
$eur = new Currency('EUR');
$usd = Currency::get('USD');

// Properties
$eur->id;          // 'EUR'
$eur->symbol;      // '€'
$eur->name;        // 'Euro'
$eur->decimals;    // 2
(string) $eur;     // 'EUR'

// Query behavior
$eur->isZeroDecimal();   // false
$eur->isThreeDecimal();  // false
$eur->isSymbolBefore();  // false
$eur->isKnown();         // true
$eur->equals($usd);      // false

// Static helpers (no instance needed)
Currency::symbolFor('GBP');  // '£'
Currency::nameFor('JPY');    // 'Yen'
Currency::allCodes();        // ['AED', 'AFN', 'ALL', ...]

// Format amounts directly
$eur->format(19.99, 'de');   // '19,99€'
$eur->format();              // '€' (symbol only)
```

---

### PageCache — HTTP Cache Header Manager

[](#pagecache--http-cache-header-manager)

Static helper for HTTP caching: sends `Cache-Control`, `Last-Modified`, and `304 Not Modified` responses.

```
use phlibs\PageCache;

PageCache::ttl(3600);              // Cache for 1 hour
PageCache::lastchange(filemtime(__FILE__));
PageCache::$pragma = 'public';
PageCache::check304();             // Send 304 if not modified
PageCache::header();               // Send cache headers
```

---

### WebCache — Web Content Cache

[](#webcache--web-content-cache)

Caches HTTP responses either in a database table (`main.cache`) or on the local filesystem (`/var/tmp/`).

```
use phlibs\WebCache;

$html = WebCache::get('https://example.com/api/data', 3600);
$json = WebCache::getJSON('https://example.com/api/data.json', 3600);
$obj  = WebCache::getObject('https://example.com/page', 86400);
```

---

### string2 — String Utilities

[](#string2--string-utilities)

Helper class for number parsing (German/European format) and string manipulation.

```
use phlibs\string2;

string2::vall('12.345,67');        // 12345.67 (German format)
string2::vall('123.45');           // 123.45 (US format)
string2::parse_phonenr('+49 170 1234567'); // '004917012345667'
string2::Abkuerzen('Long text...', 50);    // Truncated at word boundary
```

---

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

[](#requirements)

- PHP &gt;= 7.4
- MySQLi extension (for `SQL` class)
- PDO extension (for `DB` class)
- `allow_url_fopen = On` (for live exchange rates)

---

Testing
-------

[](#testing)

```
composer install
vendor/bin/phpunit
```

Tests run automatically via GitHub Actions on PHP 7.4, 8.0, 8.1, 8.2, 8.3, and 8.4.

---

Support
-------

[](#support)

[![donate via Patreon](https://camo.githubusercontent.com/1ee428805d86edc8ea4caa9e761e867f6fce6252d3bf7200db3e10d8e36eb6d8/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f446f6e6174652d50617472656f6e2d677265656e2e737667)](https://www.patreon.com/AndreasKasper)[![donate via PayPal](https://camo.githubusercontent.com/604e3db9c8751116b3f765aad0353ec7ded655bbe8aaacbc38d8c4a6b784b3ed/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f446f6e6174652d50617950616c2d677265656e2e737667)](https://www.paypal.me/AndreasKasper)[![donate via Ko-fi](https://camo.githubusercontent.com/cbb1a4b1c79b343dccd04029cbafa3b95354a4a16f2235611c5ce1f24dc5780d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f446f6e6174652d4b6f2d2d66692d677265656e2e737667)](https://ko-fi.com/andreaskasper)[![Sponsors](https://camo.githubusercontent.com/41c7b191f68762b75ed91569d44d6fffe600196ad18323a765a2efd21778c0be/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73706f6e736f72732f616e64726561736b6173706572)](https://github.com/sponsors/andreaskasper)

###  Health Score

32

—

LowBetter than 72% of packages

Maintenance60

Regular maintenance activity

Popularity6

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity48

Maturing project, gaining track record

 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

Unknown

Total

1

Last Release

3104d ago

### Community

Maintainers

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

---

Top Contributors

[![andreaskasper](https://avatars.githubusercontent.com/u/2077804?v=4)](https://github.com/andreaskasper "andreaskasper (50 commits)")

###  Code Quality

TestsPHPUnit

Code StylePHP CS Fixer

### Embed Badge

![Health badge](/badges/andreaskasper-phlibs/health.svg)

```
[![Health](https://phpackages.com/badges/andreaskasper-phlibs/health.svg)](https://phpackages.com/packages/andreaskasper-phlibs)
```

PHPackages © 2026

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