Skip to content

Collections ​

This group covers item mapping and aggregation.

Quick Map ​

FunctionWhat it does
combineAggregates existing results and stops on the first failure
combineAllAggregates existing results, returns no successes on failure, and collects every failure
mapItemsMaps raw items to per-item Result values
mapAllMaps raw items into one fail-fast result
mapCollectErrorsMaps raw items and collects keyed errors

combine ​

combine(...) takes an array of existing Result values and merges them into one aggregate result.

php
combine(array $results): self

Inputs: ​

  • $results: array of existing Result values to aggregate

Behavior: ​

  • success values are collected into an array
  • the first failure stops processing
  • metadata from processed results is merged in order

Use it when the collection should fail fast.

Use:

php
use Maxiviper117\ResultFlow\Result;

// All succeed - returns combined values
$userResult = Result::ok(['id' => 1], ['step' => 'user']);
$profileResult = Result::ok(['bio' => 'Dev'], ['step' => 'profile']);

$result = Result::combine([$userResult, $profileResult]);
// Result: ok([['id' => 1], ['bio' => 'Dev']], ['step' => 'user', 'step' => 'profile'])

// First failure stops execution
$settingsResult = Result::fail('Settings not found');

$result = Result::combine([$userResult, $settingsResult, $profileResult]);
// Result: fail('Settings not found') - profileResult never checked!

combineAll ​

combineAll(...) takes an array of existing Result values and keeps every failure. If any input fails, it returns a failure containing all errors and does not return success values.

php
combineAll(array $results): self

Inputs: ​

  • $results: array of existing Result values to aggregate

Behavior: ​

  • success values are collected while iterating
  • if any failure exists, the final result is a failure containing all errors; no success values are returned
  • metadata from all processed results is merged in order

Use it when the caller needs the full set of failure values and can ignore partial successes on a failing aggregate.

Use:

php
use Maxiviper117\ResultFlow\Result;

// All succeed - returns combined values
$result = Result::combineAll([
    Result::ok(['id' => 1]),
    Result::ok(['name' => 'John']),
]);
// Result: ok([['id' => 1], ['name' => 'John']])

// Multiple failures - collects ALL
$result = Result::combineAll([
    Result::fail('Email invalid'),
    Result::ok(['valid' => true]),
    Result::fail('Password too short'),
]);
// Result: fail(['Email invalid', 'Password too short'])
// ✅ Both errors collected, not stopped at first!
// ✅ No success values are returned when any failure exists

mapItems ​

mapItems(...) maps each raw item to its own Result and keeps the original keys.

php
mapItems(array $items, callable $fn): array

Inputs: ​

  • $items: input collection to map
  • $fn: callback that may return a plain value or a Result and receives the item and key

Behavior: ​

  • plain return values are wrapped as success
  • thrown exceptions become failure results
  • keys stay aligned with the source array

Use it when the caller needs per-item results instead of one aggregate result.

Use:

php
use Maxiviper117\ResultFlow\Result;

$rows = [
    'user1' => ['email' => 'valid@example.com'],
    'user2' => ['email' => 'invalid-email'],
    'user3' => ['email' => 'also@valid.com']
];

$validator = fn (array $row, string $key): Result =>
    filter_var($row['email'] ?? null, FILTER_VALIDATE_EMAIL)
        ? Result::ok(['email' => strtolower($row['email'])])
        : Result::fail("Invalid email for {$key}");

$results = Result::mapItems($rows, $validator);
// Returns:
// [
//     'user1' => Result::ok(['email' => 'valid@example.com']),
//     'user2' => Result::fail('Invalid email for user2'),
//     'user3' => Result::ok(['email' => 'also@valid.com']),
// ]

mapAll ​

mapAll(...) processes each item in a collection through a callback that returns a Result, with fail-fast behavior - it stops at the first failure and returns a single aggregated Result.

php
mapAll(array $items, callable $fn): self

Inputs: ​

  • $items: input collection to map
  • $fn: callback that may return a plain value or a Result and receives the item and key

Behavior: ​

  • keyed success values are returned on success
  • stops at the first failure and returns a single aggregated Result
  • metadata is merged in processing order

Use it when every item must succeed for the whole collection to succeed.

Use:

php
use Maxiviper117\ResultFlow\Result;

$csvRows = [
    1 => ['email' => 'alice@example.com', 'age' => 25],
    2 => ['email' => 'invalid-email', 'age' => 30],
    3 => ['email' => 'charlie@example.com', 'age' => 28],
];

function validateUser(array $row, int $lineNumber): Result {
    if (!filter_var($row['email'] ?? null, FILTER_VALIDATE_EMAIL)) {
        return Result::fail("Line {$lineNumber}: Invalid email");
    }
    if ($row['age'] < 18) {
        return Result::fail("Line {$lineNumber}: Must be 18+");
    }
    return Result::ok([
        'email' => strtolower($row['email']),
        'age' => $row['age']
    ]);
}

// Fail-fast on first error
$result = Result::mapAll($csvRows, validateUser);

$result->match(
    onSuccess: fn ($users) => print("✅ All users valid: " . count($users) . " imported\n"),
    onFail: fn ($error) => print("❌ {$error}\n")
);

// Output:
// ❌ Line 2: Invalid email
// Stops here! Line 3 never processed

mapCollectErrors ​

mapCollectErrors(...) processes each item in a collection through a callback that returns a Result, collecting ALL errors while processing everything. Returns a single Result with either all successes or all failures mapped by key.

php
mapCollectErrors(array $items, callable $fn): self

Inputs: ​

  • $items: input collection to map
  • $fn: callback that may return a plain value or a Result and receives the item and key

Behavior: ​

  • keyed success values are returned on success
  • failure values stay keyed on the error branch
  • never stops early, every item is evaluated

Use it for validation-style flows where the caller needs the whole error set.

Use:

php
use Maxiviper117\ResultFlow\Result;

$csvRows = [
    1 => ['email' => 'alice@example.com', 'age' => 25],
    2 => ['email' => 'invalid-email', 'age' => 30],
    3 => ['email' => 'charlie@example.com', 'age' => 15],
    4 => ['email' => 'bad-email', 'age' => 28],
];

function validateUser(array $row, int $lineNumber): Result {
    $errors = [];
    
    if (!filter_var($row['email'] ?? null, FILTER_VALIDATE_EMAIL)) {
        $errors[] = "Invalid email";
    }
    if ($row['age'] < 18) {
        $errors[] = "Must be 18+";
    }
    
    if (!empty($errors)) {
        return Result::fail(implode(', ', $errors));
    }
    
    return Result::ok(['email' => $row['email'], 'age' => $row['age']]);
}

$result = Result::mapCollectErrors($csvRows, validateUser);

$result->match(
    onSuccess: fn ($users) => print("✅ All valid: " . json_encode($users)),
    onFail: fn ($errors) => print("❌ Errors: " . json_encode($errors))
);

// Output on failure (collects ALL errors):
// ❌ Errors: {
//     "2": "Invalid email",
//     "3": "Must be 18+",
//     "4": "Invalid email"
// }

See Also ​