PHPackages                             trehinos/thor-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. trehinos/thor-common

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

trehinos/thor-common
====================

Thor common library

v1.2.1(7mo ago)1563MITPHPPHP ^8.3

Since Jan 30Pushed 7mo ago1 watchersCompare

[ Source](https://github.com/Trehinos/thor-common)[ Packagist](https://packagist.org/packages/trehinos/thor-common)[ RSS](/packages/trehinos-thor-common/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (3)Versions (13)Used By (3)

Thor Common
===========

[](#thor-common)

Reusable core utilities for the Thor framework (and standalone PHP projects).

This library provides small, focused components for day-to-day application code:

- Types: string helpers, arrays helpers, date/time helpers, placeholder formatting, a PSR-20-like clock interface
- Types\\Collection: a fluent object wrapper around PHP arrays with many convenience methods
- Types\\Safe\\Option: an Option type (Some/None) to model optional values without nulls
- Types\\Safe\\Result: a small Result type (ok/error) inspired by Rust for safer error handling
- Configuration: ArrayObject-based configuration, YAML loader/writer, path interpolation
- Validation: simple filter/validator interfaces and a regex filter
- FileSystem: utilities for files, folders, and recursive operations
- Debug: a lightweight logger with log levels and throwable handling
- Encryption: GUID-like secure token generator

The components are decoupled; you can use only the parts you need.

API inventory (by namespace)
----------------------------

[](#api-inventory-by-namespace)

- Thor\\Common\\Types
    - Strings: split, token, trimOrPad, left, right, prefix, suffix, interpolate(…, PlaceholderFormat)
    - Arrays: turnOver
    - DateTimes (implements ClockInterface): translate, getRelativeDateTime, period, get()-&gt;now()
    - PlaceholderFormat (enum): CURLY, SIGIL, SHELL with helper to build placeholders
    - ClockInterface: now()
- Thor\\Common\\Types\\Collection
    - Collection: vast fluent API over arrays (build/combine/fill/range, map/filter/reduce, slice/chunk, sort, unique, set ops, column, groupBy, indexBy, keys/values, etc.)
    - Enums: SortOrder, SortFlag, UniqueSortFlag, FilterMode, KeyCase
- Thor\\Common\\Types\\Safe
    - Option and Maybe: Some/None optional value container with unwrap/match helpers
    - Result and ResultState: ok/error result container with match helpers
- Thor\\Common\\Configuration
    - ConfigurationFromFile: load/multipleFromFile/write for YAML-based config
    - ConfigurationFolder: path interpolation via context
- Thor\\Common\\Validation
    - FilterInterface, ValidatorInterface
    - Filters\\RegexFilter: PCRE-based validator/filter
- Thor\\Common\\FileSystem
    - FileSystem: read/write/append helpers
    - Folders: createIfNotExists, copyTree, removeTree
- Thor\\Common\\Debug
    - Logger: PSR-3-like methods, static global instance, writeDebug, logThrowable
    - LogLevel (enum)
- Thor\\Common\\Encryption
    - Guid: random bytes with hex/base64 formats

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

[](#requirements)

- PHP 8.3+
- Extensions: mbstring, openssl
- Composer dependencies: symfony/yaml, symfony/var-dumper (already declared)

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

[](#installation)

Install via Composer:

```
composer require trehinos/thor-common
```

Autoloading is PSR-4 under the Thor\\Common namespace.

Quick start and examples
------------------------

[](#quick-start-and-examples)

Below are small, practical examples for the most used utilities. All namespaces assume `use` statements or fully-qualified names as needed.

### Types\\Strings

[](#typesstrings)

- Simple token interpolation with various placeholder syntaxes via PlaceholderFormat.

```
use Thor\Common\Types\Strings;
use Thor\Common\Types\PlaceholderFormat;

$template = 'Hello {name}, today is {day}!';
$out = Strings::interpolate($template, [
    'name' => 'Ada',
    'day'  => 'Thursday',
]);
// "Hello Ada, today is Thursday!"

// Different placeholder styles
Strings::interpolate('Hello $name', ['name' => 'Ada'], PlaceholderFormat::SIGIL);    // Hello Ada
Strings::interpolate('Hello ${name}', ['name' => 'Ada'], PlaceholderFormat::SHELL);  // Hello Ada
```

- Other helpers

```
Strings::left('abcdef', 3);   // 'abc'
Strings::right('abcdef', 3);  // 'def'
Strings::prefix('ID-', '42'); // 'ID-42'
Strings::suffix('42', '-OK'); // '42-OK'
// Trim specific padding and pad/truncate to length
Strings::trimOrPad('  42  ', 5, ' ', STR_PAD_LEFT); // '   42'
```

### Types\\Arrays

[](#typesarrays)

Transpose/pivot a list of associative arrays into a dictionary of lists.

```
use Thor\Common\Types\Arrays;

$input = [
    ['id' => 1, 'name' => 'Ada'],
    ['id' => 2, 'name' => 'Grace'],
];
$out = Arrays::turnOver($input);
// [ 'id' => [1,2], 'name' => ['Ada','Grace'] ]
```

### Types\\DateTimes and ClockInterface

[](#typesdatetimes-and-clockinterface)

Formatting, relative display, periods, and a simple clock provider.

```
use Thor\Common\Types\DateTimes;
use DateTimeImmutable;

DateTimes::translate('2025-10-09');              // '09/10/2025'

$now = new DateTimeImmutable('2025-10-09 18:25:00');
$yesterday = $now->modify('-1 day 14:10:00');
DateTimes::getRelativeDateTime($yesterday, 'Y-m-d', 'Yesterday', $now); // 'Yesterday 14:10'

// Generate a DatePeriod over a month by days
$start = new DateTimeImmutable('2025-10-01');
$period = DateTimes::period($start); // until last day of the month by 1 day

// ClockInterface: get "now" from the singleton DateTimes implementation
$clockNow = DateTimes::get()->now();
```

### Types\\Safe\\Result

[](#typessaferesult)

A minimal Result type to avoid throwing exceptions for expected errors.

```
use Thor\Common\Types\Safe\Result;

function divide(int $a, int $b): Result {
    if ($b === 0) {
        return Result::error('Division by zero');
    }
    return Result::ok($a / $b);
}

$quotient = divide(10, 2)
    ->unwrapOr(-1); // 5

$message = divide(1, 0)
    ->match(
        fn($ok) => "ok=$ok",
        fn($err) => "error=$err",
    ); // 'error=Division by zero'
```

### Types\\Safe\\Option

[](#typessafeoption)

A lightweight Option type to represent the presence (Some) or absence (None) of a value. Avoids passing raw nulls around and makes intent explicit.

```
use Thor\Common\Types\Safe\Option;
use Thor\Common\Types\Safe\Maybe;

// Constructing
$opt1 = Option::some('value');        // Some('value')
$opt2 = Option::none();               // None
$opt3 = Option::from($_GET['q'] ?? null); // Some or None depending on null

// Inspecting
$opt1->isSome(); // true
$opt2->isNone(); // true
$opt1->is();     // Maybe::SOME
$opt2->is();     // Maybe::NONE
$opt1->isA(Maybe::SOME); // true

// Consuming
$name = $opt3->unwrapOr('guest'); // returns the inner value or 'guest'
$val  = $opt3->unwrapOrElse(fn() => computeDefault());

// Pattern matching style
$msg = $opt3->matches(
    fn($v) => "got=$v",
    fn()   => "none",
);

// Exceptions on None
try {
    $must = $opt2->unwrap(); // throws RuntimeException if None
} catch (\Throwable $e) {
    // handle
}

// Or throw custom exception
$must = $opt2->unwrapOrThrow(new \InvalidArgumentException('missing value'));
```

### Validation

[](#validation)

FilterInterface and ValidatorInterface define small contracts. A ready-to-use RegexFilter is provided.

```
use Thor\Common\Validation\Filters\RegexFilter;

$filter = new RegexFilter('/^[a-z]+$/i');

$ok = $filter->filter('Foobar'); // 'Foobar'
$fail = $filter->filter('Foo 123'); // null (per filter_var behavior)
```

### Configuration

[](#configuration)

ArrayObject-based configuration with YAML loading/writing and path interpolation.

```
use Thor\Common\Configuration\ConfigurationFromFile;
use Thor\Common\Configuration\ConfigurationFolder;

// Load a single config from YAML (provide path without extension)
$app = ConfigurationFromFile::fromFile('/path/to/app');
$dsn = $app->database['dsn'] ?? null;

// Load multiple configs from a YAML list
$items = ConfigurationFromFile::multipleFromFile('/path/to/list', ConfigurationFromFile::class);

// Write configuration to a YAML file
$app->write('/path/to/out.yml');

// Interpolate paths from a context
$cfgFolder = new ConfigurationFolder(['env' => 'prod', 'name' => 'myapp']);
$resolved = $cfgFolder->getPath('/opt/{name}/{env}/config.yml'); // '/opt/myapp/prod/config.yml'
```

### Debug

[](#debug)

A lightweight logger with log levels and an easy way to record throwables.

```
use Thor\Common\Debug\Logger;
use Thor\Common\Debug\LogLevel;

// Initialize a global logger (file will be created under base path)
Logger::set(LogLevel::DEBUG, __DIR__ . '/var/');

Logger::info('Server started');
Logger::error('Something went wrong', ['context' => 'value']);

try {
    throw new RuntimeException('Boom');
} catch (Throwable $e) {
    Logger::logThrowable($e); // writes ERROR + details at DEBUG level
}
```

### FileSystem

[](#filesystem)

Convenience functions to work with files and folders.

```
use Thor\Common\FileSystem\Folders;
use Thor\Common\FileSystem\FileSystem;

Folders::createIfNotExists(__DIR__ . '/cache');
FileSystem::write(__DIR__ . '/cache/app.log', "Started\n");
FileSystem::appendIfExists(__DIR__ . '/cache/app.log', "Tick\n");

// Recursively copy/remove
Folders::copyTree(__DIR__ . '/assets', __DIR__ . '/public');
$deleted = Folders::removeTree(__DIR__ . '/public', mask: '.*\\.(tmp|bak)$');
```

### Encryption

[](#encryption)

Secure random tokens and flexible string formats.

```
use Thor\Common\Encryption\Guid;

$g = new Guid(16);
(string)$g;       // Uppercase hex grouped like a GUID
$g->getHex();     // Lowercase hex
$g->getBase64();  // Base64
Guid::hex();      // Fresh lowercase hex string
```

### Types\\Collection (fluent array wrapper)

[](#typescollection-fluent-array-wrapper)

A rich wrapper around PHP arrays offering dozens of familiar operations (map/filter/reduce, set ops, sorting, chunking, etc.).

```
use Thor\Common\Types\Collection\Collection;

$users = new Collection([
    ['id' => 1, 'name' => 'Ada'],
    ['id' => 2, 'name' => 'Grace'],
]);

$names = $users->column('name')->values()->toArray(); // ['Ada','Grace']
```

Note: See the source of Types/Collection for the full list of methods and options.

Running tests
-------------

[](#running-tests)

This repository uses PHPUnit 10.x. Install dev dependencies and run tests:

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

Versioning and stability
------------------------

[](#versioning-and-stability)

This package follows semantic versioning as much as possible. Minor versions may add features without breaking changes. Check the CHANGELOG or git history for details.

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

[](#contributing)

Issues and PRs are welcome. Please include tests for bug fixes and new features when possible.

License
-------

[](#license)

MIT License. See LICENSE file. © 2021–2025 Sébastien Geldreich

###  Health Score

41

—

FairBetter than 88% of packages

Maintenance69

Regular maintenance activity

Popularity10

Limited adoption so far

Community12

Small or concentrated contributor base

Maturity63

Established project with proven stability

 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

Every ~56 days

Recently: every ~0 days

Total

12

Last Release

211d ago

### Community

Maintainers

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

---

Top Contributors

[![Trehinos](https://avatars.githubusercontent.com/u/3908278?v=4)](https://github.com/Trehinos "Trehinos (17 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/trehinos-thor-common/health.svg)

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

###  Alternatives

[orchestra/canvas

Code Generators for Laravel Applications and Packages

21017.2M157](/packages/orchestra-canvas)[cognesy/instructor-php

The complete AI toolkit for PHP: unified LLM API, structured outputs, agents, and coding agent control

310107.9k1](/packages/cognesy-instructor-php)[civicrm/civicrm-core

Open source constituent relationship management for non-profits, NGOs and advocacy organizations.

728272.9k17](/packages/civicrm-civicrm-core)[netgen/content-browser

Netgen Content Browser is a Symfony bundle that provides an interface which selects items from any kind of backend and returns the IDs of selected items back to the calling code.

14112.1k8](/packages/netgen-content-browser)

PHPackages © 2026

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