PHPackages                             pwm/deepend - 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. pwm/deepend

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

pwm/deepend
===========

A library for scheduling dependent task execution.

v1.1.0(8y ago)73.6kMITPHPPHP &gt;=7.1.0

Since Jul 12Pushed 8y ago1 watchersCompare

[ Source](https://github.com/pwm/deepend)[ Packagist](https://packagist.org/packages/pwm/deepend)[ Docs](https://github.com/pwm/deepend)[ RSS](/packages/pwm-deepend/feed)WikiDiscussions master Synced 1mo ago

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

DeepEnd
=======

[](#deepend)

[![Build Status](https://camo.githubusercontent.com/9d4aaaf5bdb8d9ae99d151d16219658858cc138823ab65efcc5ddd4d0e71bfba/68747470733a2f2f7472617669732d63692e6f72672f70776d2f64656570656e642e7376673f6272616e63683d6d6173746572)](https://travis-ci.org/pwm/deepend)[![codecov](https://camo.githubusercontent.com/188347211793b77a9dff2772e074cec7fb93b531818eb759c81e9ce4c923c2aa/68747470733a2f2f636f6465636f762e696f2f67682f70776d2f64656570656e642f6272616e63682f6d61737465722f67726170682f62616467652e737667)](https://codecov.io/gh/pwm/deepend)[![Maintainability](https://camo.githubusercontent.com/74ac74a5f094d7ad53bac31f2fd4ca37d3f13e946975111a4984896df31c64ee/68747470733a2f2f6170692e636f6465636c696d6174652e636f6d2f76312f6261646765732f35663239306637636130346163346630333265312f6d61696e7461696e6162696c697479)](https://codeclimate.com/github/pwm/deepend/maintainability)[![Test Coverage](https://camo.githubusercontent.com/253998ddebdd0cafb039a0ddef69d364bce48b3d5edc10b59663f34df2386874/68747470733a2f2f6170692e636f6465636c696d6174652e636f6d2f76312f6261646765732f35663239306637636130346163346630333265312f746573745f636f766572616765)](https://codeclimate.com/github/pwm/deepend/test_coverage)[![License: MIT](https://camo.githubusercontent.com/fdf2982b9f5d7489dcf44570e714e3a15fce6253e0cc6b5aa61a075aac2ff71b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d79656c6c6f772e737667)](https://opensource.org/licenses/MIT)

A library for scheduling dependent task execution.

The goal is to be able to build a network of dependent entities, eg. task ids, which can then be sorted into a correct execution order. This means that if task B depends on task A then task A comes before task B in the sorted order.

Table of Contents
-----------------

[](#table-of-contents)

- [Requirements](#requirements)
- [Installation](#installation)
- [Usage](#usage)
- [How it works](#how-it-works)
- [Tests](#tests)
- [Changelog](#changelog)
- [Licence](#licence)

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

[](#requirements)

PHP 7.1+

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

[](#installation)

```
$ composer require pwm/deepend

```

Usage
-----

[](#usage)

Below is a simple example of creating dependencies between 4 tasks:

```
// Create an empty store
$deepEnd = new DeepEnd();

// Add some entries, in our example they are the task ids
$deepEnd->add('t1');
$deepEnd->add('t2');
$deepEnd->add('t3');
$deepEnd->add('t4');

// Specify dependencies between them. A pointing to B, ie. an arrow from A to B,
// means that B depends on A therefore A has to happen before B can happen.
$deepEnd->draw((new Arrow)->from('t1')->to('t2'));
$deepEnd->draw((new Arrow)->from('t1')->to('t3'));
$deepEnd->draw((new Arrow)->from('t2')->to('t4'));

// Get a valid execution order
$order = $deepEnd->sort(); // $order = ['t1', 't3', 't2', 't4']
```

You can also add data (including functions and objects) to your tasks for later use. For this case use the `sortToMap()` method, which returns a map with ids as keys and the added data as values. Using the above example of 4 tasks we could do the following:

```
function taskRunner(string $taskId, string $taskData): void
{
    echo sprintf('Running task %s with data %s ... done.', $taskId, $taskData) . PHP_EOL;
}

$deepEnd = new DeepEnd();

$deepEnd->add('t1', 't1-data');
$deepEnd->add('t2', 't2-data');
$deepEnd->add('t3', 't3-data');
$deepEnd->add('t4', 't4-data');

$deepEnd->draw((new Arrow)->from('t1')->to('t2'));
$deepEnd->draw((new Arrow)->from('t1')->to('t3'));
$deepEnd->draw((new Arrow)->from('t2')->to('t4'));

$orderedTasks = $deepEnd->sortToMap();
foreach ($orderedTasks as $taskId => $taskData) {
    taskRunner($taskId, $taskData);
}

// Running task t1 with data t1-data ... done.
// Running task t3 with data t3-data ... done.
// Running task t2 with data t2-data ... done.
// Running task t4 with data t4-data ... done.
```

How it works
------------

[](#how-it-works)

When adding entries via the `add()` method and arrows via the `draw()` method you are actually building a graph, more specifically a directed acyclic graph (DAG), where nodes are added via `add()` and edges/arrows via `draw()`.

Every time you want to draw a new arrow from node A to node B DeepEnd checks whether it would create a cycle and if the answer is yes then it will tell you in the form of an exception. The way this is done is that, before drawing the arrow, DeepEnd checks whether A is already reachable from B, ie. whether there's a path from B to A. If there is, then an arrow from A to B would lead to a cycle as you can already get from B to A and then, via the new arrow, back to B.

Once you have your graph built the `sort()` method can be used to do what is called a topological sort on your DAG. This is done using depth first search where DeepEnd incrementally indexes nodes as it leaves them after visiting. This is known as postordering. Once finished it will sort the nodes in reverse order, starting with nodes with the highest post order index. This results in an order where nodes that depend on other nodes come after their dependencies, which is the order we are after.

Tests
-----

[](#tests)

```
$ vendor/bin/phpunit
$ composer phpcs
$ composer phpstan

```

Changelog
---------

[](#changelog)

[Click here](changelog.md)

Licence
-------

[](#licence)

[MIT](LICENSE)

###  Health Score

31

—

LowBetter than 68% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity25

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity59

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 ~1 days

Total

2

Last Release

3231d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/361d01dea838dfee1327e7c6e803e7f53ae92b48d6971bcaeca43d3d49504c19?d=identicon)[pwm](/maintainers/pwm)

---

Top Contributors

[![pwm](https://avatars.githubusercontent.com/u/195513?v=4)](https://github.com/pwm "pwm (24 commits)")

---

Tags

graph-algorithmsscheduled-taskstopological-sorttopological sortGraph algorithmsscheduled-tasks

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/pwm-deepend/health.svg)

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

###  Alternatives

[marcj/topsort

High-Performance TopSort/Dependency resolving algorithm

24715.6M50](/packages/marcj-topsort)[graphp/algorithms

Common mathematical graph algorithms implemented in PHP

1402.9M14](/packages/graphp-algorithms)[letournel/path-finder

Path finder algorithm

142.0k](/packages/letournel-path-finder)

PHPackages © 2026

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