PHPackages                             mensbeam/fork - 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. mensbeam/fork

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

mensbeam/fork
=============

Runs code concurrently by forking processes

1.0.1(2mo ago)08MITPHPPHP ^8.1

Since Jul 1Pushed 2mo agoCompare

[ Source](https://github.com/mensbeam/Fork)[ Packagist](https://packagist.org/packages/mensbeam/fork)[ RSS](/packages/mensbeam-fork/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (7)Versions (3)Used By (0)

Fork
====

[](#fork)

*Fork* is a library for running jobs concurrently in PHP. It works by forking the main process into separate tasks using PHP's [`pcntl`](https://www.php.net/manual/en/book.pcntl.php) and [`sockets`](https://www.php.net/manual/en/book.sockets.php) extensions. So, it should go without saying that this library will not work on Windows.

There is an existing library for forking processes, [spatie/fork](https://github.com/spatie/fork). This library on its surface is very similar, but internally it's quite a bit different. Unlike `spatie/fork`, `mensbeam/fork` does not return an array of returned values from all tasks after all of them have finished. Instead, it uses callbacks to handle output as each task completes. This design prevents potential memory exhaustion when running a large number of tasks, as we encountered when using `spatie/fork`. Handling output immediately as tasks finish is more scalable and efficient.

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

[](#requirements)

- PHP &gt;= 8.1
- [ext-mbstring](https://www.php.net/manual/en/book.mbstring.php)
- [ext-pcntl](https://www.php.net/manual/en/book.pcntl.php)
- [ext-sockets](https://www.php.net/manual/en/book.sockets.php)
- [mensbeam/self-sealing-callable](https://code.mensbeam.com/MensBeam/SelfSealingCallable) ^1.0

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

[](#installation)

Install using Composer:

```
composer require mensbeam/fork
```

Usage
-----

[](#usage)

Here is a simple example. `Fork->run()` can accept an array or an `\Iterator` of callables to run concurrently and will execute them. This means it can also accept a generator to continuously run tasks concurrently.

```
use MensBeam\Fork;

function gen(): \Generator {
    foreach (range(1, 5) as $n) {
        yield function () use ($n) {
            $delay = rand(1, 5);
            sleep($delay);
            return [ $n, $delay ];
        };
    }
}

(new Fork())->after(function(array $output) {
    echo "{$output['data'][0]}: {$output['data'][1]}\n";
})->run(gen());
```

Example output:

```
4: 2
3: 2
2: 3
5: 3
1: 5

```

---

Callbacks
---------

[](#callbacks)

You can use `before()` and `after()` to register callbacks to run **before or after each task**. You can register different callbacks for the parent and child processes.

---

Concurrency
-----------

[](#concurrency)

You can limit how many tasks run concurrently using `concurrent()`.

```
use MensBeam\Fork;

(new Fork())->concurrent(2)->run([
    fn() => sleep(1),
    fn() => sleep(1),
    fn() => sleep(1)
]);
```

---

Timeouts
--------

[](#timeouts)

You can set a timeout (in seconds) for each child process:

```
use MensBeam\Fork;

(new Fork())->timeout(5)->run([
    fn() => sleep(10), // This will timeout
    fn() => sleep(2)
]);
```

When a task times out, a `TimeoutException` is thrown inside the child process, and a `ThrowableContext` object is sent back to the parent.

---

Stopping tasks
--------------

[](#stopping-tasks)

You can stop all currently running and queued tasks from within an `after()` callback:

```
use MensBeam\Fork;

$f = new Fork();
$f->after(function(array $output) use ($f) {
    if ($output['data'] === 'stop') {
        $f->stop();
    }
})->run([
    fn() => 'continue',
    fn() => 'stop',
    fn() => 'never runs'
]);
```

---

ThrowableContext
----------------

[](#throwablecontext)

When a task throws an exception or error in a child process, a `ThrowableContext` instance is returned to the parent.

### What it includes

[](#what-it-includes)

- Error code
- File and line where the throwable was thrown
- Message
- Class type
- Optional stack trace (enabled via `Fork::$tracesInThrowableContexts`)
- Any previous throwable chain

---

### Example

[](#example)

```
use MensBeam\Fork;

(new Fork())->after(function(array $output) {
    if ($output['data'] instanceof MensBeam\Fork\ThrowableContext) {
        echo "Child failed with: " . $output['data']->getMessage() . "\n";
    } else {
        echo "Child succeeded with: " . $output['data'] . "\n";
    }
})->run([
    fn() => throw new \RuntimeException("Something went wrong!"),
    fn() => "All good"
]);
```

---

Handling traces
---------------

[](#handling-traces)

You can enable including stack traces in `ThrowableContext` objects:

```
use MensBeam\Fork;
Fork::$tracesInThrowableContexts = true;
```

Keep in mind there are some minor limitations, however. Anything that can't be serialized such as Generators, Closures, etc. are all sanitized to strings denoting what they were before being replaced.

---

Throwing exceptions inside the fork
-----------------------------------

[](#throwing-exceptions-inside-the-fork)

By default, exceptions inside child processes are caught and sent as `ThrowableContext` objects. If you'd like them to be **thrown, crash the child process, and therefore be printed** (for debugging or crash reporting), set:

```
use MensBeam\Fork;
Fork::$throwInFork = true;

(new Fork())->after(function(array $output) {
    echo "Ook!\n";
})->run([
    fn() => throw new \RuntimeException('Eek!'))
]);
```

Example output:

```
PHP Fatal error:  Uncaught RuntimeException: Eek! in /path/to/test.php:42
Ook!

```

---

License
-------

[](#license)

MIT License. See [LICENSE.md](LICENSE.md) and [AUTHORS.md](AUTHORS.md) for details.

###  Health Score

38

—

LowBetter than 83% of packages

Maintenance87

Actively maintained with recent releases

Popularity5

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity47

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

Every ~302 days

Total

2

Last Release

65d ago

### Community

Maintainers

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

---

Top Contributors

[![dustinwilson](https://avatars.githubusercontent.com/u/1885928?v=4)](https://github.com/dustinwilson "dustinwilson (18 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/mensbeam-fork/health.svg)

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

PHPackages © 2026

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