timefrontiers/php-instance-error

PHP Instance Error handler with access-based filtering

Maintainers

Package info

github.com/timefrontiers/php-instance-error

pkg:composer/timefrontiers/php-instance-error

Transparency log

Statistics

Installs: 44

Dependents: 1

Suggesters: 5

Stars: 0

Open Issues: 0

v1.1.1 2026-08-20 07:06 UTC

This package is auto-updated.

Last update: 2026-08-20 07:45:58 UTC


README

InstanceError is the standard reader and access-rank filter for error collections produced by TimeFrontiers\Helper\HasErrors. It preserves the established five-element tuple and context grouping used across TimeFrontiers packages.

Installation

composer require timefrontiers/php-instance-error

The package requires timefrontiers/php-error-log, so the public log() API is available after every normal Composer installation. timefrontiers/php-session remains optional; without a valid global session, extraction defaults to guest rank.

Canonical error shape

Every accepted error is a five-element list:

/** @var array{0: int, 1: int, 2: string, 3: string, 4: int} $error */
$error = [$minimumRank, $code, $message, $file, $line];

Errors are grouped by a non-empty context:

/** @var array<string, list<array{0: int, 1: int, 2: string, 3: string, 4: int}>> $errors */
$errors = [
  'validation' => [
    [0, 400, 'Invalid email address.', '/app/User.php', 42],
  ],
];

Malformed contexts and tuples are rejected during extraction. In particular, a missing or invalid minimum rank never defaults to guest. Safe integer-like strings in numeric tuple positions are normalized to integers; fields are not invented when missing.

Extracting errors for display

Objects using HasErrors::getErrors() are supported directly. A public legacy $errors property is used only when there is no callable getter.

use TimeFrontiers\InstanceError;

$extractor = new InstanceError($service);

// Grouped tuples visible to the current session rank.
$visible = $extractor->get();

// Flat list of tuples from one context.
$validation = $extractor->get('validation');

// Flat list of strings from one context.
$validationMessages = $extractor->get('validation', true);

get('', true) does not flatten across contexts. It returns grouped message lists:

$groupedMessages = $extractor->get('', true);
// ['validation' => ['Invalid email address.'], 'save' => ['Save failed.']]

$flatMessages = $extractor->messages();
// ['Invalid email address.', 'Save failed.']

Helper methods operate only on entries visible to the resolved rank:

if ($extractor->has('validation')) {
  $first = $extractor->first('validation');
  $count = $extractor->count('validation');
}

Rank filtering is defense in depth, not secret scrubbing. Public responses must not contain SQL, stack traces, absolute paths, provider payloads, credentials, tokens, cookies, authorization headers, card data, or raw driver messages.

Rank resolution

The effective visibility rank is resolved in this order:

  1. An explicit AccessRank constructor override.
  2. An explicit integer constructor override.
  3. true, which deliberately bypasses filtering with PHP_INT_MAX.
  4. The callable global $session->access_rank() method.
  5. A public legacy global $session->access_rank property.
  6. AccessRank::GUEST->value.

Session method/property results may be an AccessRank, integer, or integer-like string. Invalid, negative, inaccessible, or throwing session values fail to guest. Future integer ranks are not capped; the current enum includes AccessRank::OWNER at rank 14.

use TimeFrontiers\AccessRank;
use TimeFrontiers\InstanceError;

$developerView = new InstanceError($service, AccessRank::DEVELOPER);
$rankFiveView = new InstanceError($service, 5);

Explicit rank overrides, the true bypass, and all() are trusted server-side technical/debug operations. Never populate an override from a query parameter, form field, header, token claim, or any other untrusted request input. Never return all() or unrestricted output in a public response.

Technical logging

log() applies the extractor's current visibility rank and writes one ResponseStatus::PROCESS_ERROR record per selected context. Each log detail keeps the tuple's own code separate from the response-status prefix.

use TimeFrontiers\InstanceError;

// Logs only errors visible to the normal session-resolved extractor.
$displayExtractor = new InstanceError($service);
$displayExtractor->log('validation');

// Trusted server-side flow: deliberately include all technical entries.
$technicalExtractor = new InstanceError($service, true);
$technicalExtractor->log();

// Preserve the exact custom-file behavior through ErrorLog::setFile().
$technicalExtractor->log('database', '/var/log/my-app/database-errors.log');

A supplied context that does not exist, a failed write, or a logger exception returns false and adds a safe developer-visible diagnostic to the extractor's own HasErrors collection.

Logging does not make secrets safe to store. The logger protects its record delimiters, but application and package code must prevent credentials, tokens, card data, raw provider payloads, and other secrets from entering error messages in the first place.

Adding canonical errors

put() is a programmer-facing API. It throws InvalidArgumentException for a blank context or malformed tuple.

$extractor->put('custom', [
  AccessRank::GUEST->value,
  400,
  'Something went wrong.',
  __FILE__,
  __LINE__,
]);

Using HasErrors

use TimeFrontiers\Helper\HasErrors;

final class Service {
  use HasErrors;

  public function process():bool {
    $this->_userError('process', 'The request could not be processed.', 400);
    return false;
  }
}

The current protected _addError() signature is:

_addError(
  string $context,
  string $message,
  int $minimumRank = AccessRank::GUEST->value,
  int $code = 256,
  string $file = '',
  int $line = 0,
): void

Development

composer validate --strict
composer install
composer test
composer analyse
composer audit

Dependencies

  • PHP 8.5 or newer
  • timefrontiers/php-core
  • timefrontiers/php-has-errors
  • timefrontiers/php-error-log
  • Optional: timefrontiers/php-session for global session-rank resolution

License

MIT