php-cooper

Cooper
in package

FinalYes

Loads CASC config files (see `casc/CASC.md`) into native PHP values.

loadFile()/loadString() (and loadFileTraced(), which also reports what the load depended on) run the whole pipeline: parse, evaluate (loops and imports expanded in place), merge (secret-wrapping included), and resolve every @{...}/${...}/%{...}/!{...}/ !Name(...) reference. loadFile() caches everything before the resolve step (see Cache).

The result

A block/map is an associative array (string keys -- PHP turns a numeric-looking one into an int key), a list is a list array. Everything a PHP array cannot represent faithfully gets a value class under JOetjen\Cooper\Value: CooperTuple (tuples are never lists, CASC.md §6.11), CooperAtom (level = info), CooperDuration, CooperBytes, CooperIPv4/CooperIPv6, CooperDate/CooperTime/ CooperLocalDateTime, and CooperSecret around every *key value. An offset date-time is a CooperDateTime in UTC; inf is INF.

Options

Both methods take the same options array:

  • env (array<string, string>) -- an override layer for ${...}, on top of .env files and the real environment (see Dotenv).
  • dotenv (bool), dotenvEnv (?string), dotenvFiles (list<string>), dotenvDir (string, default: the project root -- the Composer root package's directory, else the working directory), dotenvOverride (bool) -- .env file loading; see Dotenv for the layering rules.
  • root (string) -- the directory a bare import resolves against. loadFile() defaults it to the file's own directory, loadString() to the working directory.
  • resolvers (array<string, callable(string): mixed>) -- one per !{name:...} resolver (CASC.md §7.4). Return the value, or throw.
  • tags (array<string, callable(mixed): mixed>) -- !Name(...) tags beyond the built-in int, float, bool, duration, bytes, trim, downcase, upcase, module (§7.5). A tag given as a LiteralTag takes only a string literal written in the document, and refuses the load otherwise (see LiteralTag).
  • modules (array<string, mixed>) -- what !module("Name") gives back (§7.5), by the name exactly as written (case-sensitive, after trimming); typically a class-string. A name it does not hold is translated by convention: Acme.Payments -> "Acme\Payments". Either way the class is never loaded or checked. The name itself must be dot-separated PascalCase, mapped or not.
  • importSchemes (array<string, callable(string): string>) -- one per import "scheme://..." scheme (§9.3), returning CASC source.
  • cache (bool, default true) -- loadFile() only.
  • envValue (callable(EnvReference, \Closure(): mixed): mixed) -- decides what a ${NAME} written as a value resolves to, for a host that resolves the environment later than the load (a framework keeping it a runtime placeholder). It receives the reference, described by an EnvReference, and a closure giving the value Cooper would have resolved; what it returns stands in the reference's place. A ${NAME} that shapes the document -- a ${?NAME} guard, an import path, an interpolated key -- never reaches it. A name it answers for without calling the closure was never read, and is not in a LoadTrace's $env. Without it, every ${NAME} resolves from the environment, as it always has.

Unregistered resolvers, tags, and schemes are always load-time errors naming the offender (§9.4).

Errors

Every failure throws CooperError, whose $stage says which part of the pipeline failed. Malformed options throw \InvalidArgumentException.

Table of Contents

Methods

loadFile()  : array<string|int, mixed>
Reads and loads the CASC file at `$path`. Bare imports resolve relative to the file's own directory, and an import cycle back to the file itself is caught on the first repeat.
loadFileTraced()  : LoadTrace
`loadFile()`, together with what the load depended on: every file it read, every import's expansion, and every environment variable it read, with the value it saw (see `LoadTrace`). The config is the same one `loadFile()` returns, cached the same way.
loadString()  : array<string|int, mixed>
Loads `$source` -- a complete CASC file's text, version header included -- through the same pipeline as `loadFile()`, without caching (there is no file to key a cache on). Bare imports need a real `root`, unless they go through `importSchemes`.
__construct()  : mixed
resolve()  : array{0: array, 1: list}

Methods

loadFile()

Reads and loads the CASC file at `$path`. Bare imports resolve relative to the file's own directory, and an import cycle back to the file itself is caught on the first repeat.

public static loadFile(string $path[, array<string, mixed> $options = [] ]) : array<string|int, mixed>

Cached by default: the pre-resolve tree is reused as long as the file and everything it imports are unchanged on disk, and the environment variables that shaped it still hold the same values (see Cache). ${...} values are always re-read.

Parameters
$path : string

the CASC file, relative to the working directory or absolute

$options : array<string, mixed> = []

see the class documentation

Tags
throws
CooperError

when loading fails

InvalidArgumentException

on malformed options

Return values
array<string|int, mixed> —

the loaded config

loadFileTraced()

`loadFile()`, together with what the load depended on: every file it read, every import's expansion, and every environment variable it read, with the value it saw (see `LoadTrace`). The config is the same one `loadFile()` returns, cached the same way.

public static loadFileTraced(string $path[, array<string, mixed> $options = [] ]) : LoadTrace

For a caller that keeps the result where Cache cannot see it -- a compiled file, a shared store -- and must tell for itself when that copy has gone stale.

Parameters
$path : string

the CASC file, relative to the working directory or absolute

$options : array<string, mixed> = []

see the class documentation

Tags
throws
CooperError

when loading fails

InvalidArgumentException

on malformed options

Return values
LoadTrace —

the config and what it depended on

loadString()

Loads `$source` -- a complete CASC file's text, version header included -- through the same pipeline as `loadFile()`, without caching (there is no file to key a cache on). Bare imports need a real `root`, unless they go through `importSchemes`.

public static loadString(string $source[, array<string, mixed> $options = [] ]) : array<string|int, mixed>
Parameters
$source : string

the CASC text

$options : array<string, mixed> = []

see the class documentation

Tags
throws
CooperError

when loading fails

InvalidArgumentException

on malformed options

Return values
array<string|int, mixed> —

the loaded config

__construct()

private __construct() : mixed

resolve()

private static resolve(TreeResult $result, Options $opts, array<string, string> $env) : array{0: array, 1: list}
Parameters
$result : TreeResult
$opts : Options
$env : array<string, string>
Return values
array{0: array, 1: list} —

the config, and every ${NAME} resolution read

On this page

Search results