PHPackages                             rikta/timed-loop - 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. rikta/timed-loop

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

rikta/timed-loop
================

Run an endless loop until it returns something different, but limit it by time

1.0.1(4y ago)09[1 PRs](https://github.com/MadWillow/timed-loop/pulls)2MITPHPCI passing

Since Sep 19Pushed 2mo ago1 watchersCompare

[ Source](https://github.com/MadWillow/timed-loop)[ Packagist](https://packagist.org/packages/rikta/timed-loop)[ RSS](/packages/rikta-timed-loop/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (3)Versions (4)Used By (2)

TimedLoop
=========

[](#timedloop)

[![packagist name](https://camo.githubusercontent.com/c45a6a5c1bc7dd537d986b07bce23a6659bf4b61433f8533e433e8f35f3e92ac/68747470733a2f2f62616467656e2e6e65742f7061636b61676973742f6e616d652f72696b74612f74696d65642d6c6f6f70)](https://packagist.org/packages/rikta/timed-loop)[![version](https://camo.githubusercontent.com/47010a233678a715a5504443f0ddb25fda69e92751e69cec4e5118689a65a689/68747470733a2f2f62616467656e2e6e65742f7061636b61676973742f762f72696b74612f74696d65642d6c6f6f702f6c61746573743f6c6162656c26636f6c6f723d677265656e)](https://github.com/RiktaD/timed-loop/releases)[![php version](https://camo.githubusercontent.com/b0f2ad025a9d46300c5b4da99cc0aa5513ccfa081e038c636e50381d50e3d2b8/68747470733a2f2f62616467656e2e6e65742f7061636b61676973742f7068702f72696b74612f74696d65642d6c6f6f70)](https://github.com/RiktaD/timed-loop/blob/main/composer.json)

[![license](https://camo.githubusercontent.com/734c64caab274e4fd48ca6ddc00ca8c156e56890d15b122e83c65168c0f139a5/68747470733a2f2f62616467656e2e6e65742f6769746875622f6c6963656e73652f72696b7461642f74696d65642d6c6f6f70)](https://github.com/RiktaD/timed-loop/blob/main/LICENSE.md)[![GitHub commit activity](https://camo.githubusercontent.com/b5f7e3bfdd6649a495341275895921ebb0e7497dce97405ebbefcbfeeb35ed2c/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f636f6d6d69742d61637469766974792f6d2f72696b7461642f74696d65642d6c6f6f70)](https://github.com/RiktaD/timed-loop/graphs/commit-activity)[![open issues](https://camo.githubusercontent.com/2e070e01c0d887f42ba5d66cc7395195bd1c53e64f41e3298a5cc725e4d7a1ec/68747470733a2f2f62616467656e2e6e65742f6769746875622f6f70656e2d6973737565732f72696b7461642f74696d65642d6c6f6f70)](https://github.com/RiktaD/timed-loop/issues?q=is%3Aopen+is%3Aissue)[![closed issues](https://camo.githubusercontent.com/df8cb50a7c17383281a4faea050c297eee3110893e0870bf1dd544486b434c82/68747470733a2f2f62616467656e2e6e65742f6769746875622f636c6f7365642d6973737565732f72696b7461642f74696d65642d6c6f6f70)](https://github.com/RiktaD/timed-loop/issues?q=is%3Aissue+is%3Aclosed)

[![ci](https://camo.githubusercontent.com/0a2a3fd0e031499e465fac33cd4a352845cc21bb52e3a9e2fabef503adcdcf8d/68747470733a2f2f62616467656e2e6e65742f6769746875622f636865636b732f72696b7461642f74696d65642d6c6f6f703f6c6162656c3d6369)](https://github.com/RiktaD/timed-loop/actions?query=branch%3Amain+workflow%3A%22Testing+Query%22+workflow%3Acreate-release++)[![dependabot](https://camo.githubusercontent.com/d9a7fc68a802ebc260b04bb37bf0922726ee981d8d50c4d2c50f037da7f87974/68747470733a2f2f62616467656e2e6e65742f6769746875622f646570656e6461626f742f72696b7461642f74696d65642d6c6f6f70)](https://dependabot.com)[![maintainability score](https://camo.githubusercontent.com/77b47e9f1d1fbc6fb0916917a813663d9f51a5a9a4a486c88c3f9a296fb63260/68747470733a2f2f62616467656e2e6e65742f636f6465636c696d6174652f6d61696e7461696e6162696c6974792f52696b7461442f74696d65642d6c6f6f70)](https://codeclimate.com/github/RiktaD/timed-loop)[![tech debt %](https://camo.githubusercontent.com/44b09cd029ecbcd70e6a30b242b0d01169fcd9c8feaf7e132d2b3be4eef82f24/68747470733a2f2f62616467656e2e6e65742f636f6465636c696d6174652f746563682d646562742f52696b7461442f74696d65642d6c6f6f70)](https://codeclimate.com/github/RiktaD/timed-loop/issues)[![maintainability issues](https://camo.githubusercontent.com/a1564baa4156c2769714de4e64c8ec05b1fb9acdaedcf34b5138ed7aebe77f52/68747470733a2f2f62616467656e2e6e65742f636f6465636c696d6174652f6973737565732f52696b7461442f74696d65642d6c6f6f703f6c6162656c3d6d61696e7461696e6162696c697479253230697373756573)](https://codeclimate.com/github/RiktaD/timed-loop/issues)

Run an endless loop until it returns something different, but limit it by time

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

[](#installation)

`composer require rikta/timed-loop`

Usage
-----

[](#usage)

### Minimum

[](#minimum)

Use Case: We want to check that an endpoint is reachable

Until we get any http-response, `@file_get_contents(...)` simply returns `false` *(maybe a bit hacky? anyway, example!)*which is also the default "continue"-value to keep the loop going.

As soon as the endpoint is up, `@file_get_contents(...)` will return the textual representation.

We expect the result in a few milliseconds or seconds, therefore the default timeout of 10 seconds is sufficient.

```
use Rikta\TimedLoop\TimedLoop;
$loop = new TimedLoop(fn () => @file_get_contents('http://localhost:8080/health.php'));
$healthResult = $loop();
```

### Verbose

[](#verbose)

A more verbose example:

```
use Rikta\TimedLoop\TimedLoop;

class RemoteRepositoryAdapter {
    public function getNextItem(Repository $repository, Options $options): ?object { /*...*/ }
    public function hasNextItem(Repository $repository, Options $options): bool { /*...*/ }
}
$options = new Options(/*...*/);
$repository = new Repository(/*...*/);
$repositoryAdapter = new RemoteRepositoryAdapter;

// instead of an anonymous function you can also provide callables via array
// the first element is the object/class-string/'self', the second one the method
$loop = new TimedLoop([$repositoryAdapter, 'getNextItem']);

// by default it waits until something else than `false`
$loop->untilItReturnsSomethingElseThan(null);

// by default it retries it after 50000 microseconds (1/1_000_000 second)
$loop->retryingAfterMicroseconds(100_000);

// by default it throws an exception after 10 seconds
$loop->forMaximumSeconds(60);

// run the loop until the callable returns a non-null-value, and return said value
$nextItem = $loop($repository, $options);
// you can also use $loop->invoke($repository, $options) if you don't like invoking variables ;)
```

all methods are chainable, therefore the following call would be equivalent:

```
$nextItem = (new TimedLoop([$repositoryAdapter, 'getNextItem']))
            ->untilItReturnsSomethingElseThan(null)
            ->retryingAfterMicroseconds(100_000)
            ->forMaximumSeconds(60)
            ->invoke($repository, $options);
```

### Static

[](#static)

If you're happy with the defaults, you can also just use the static `loop($callable, ...$args)`

```
// loops until hasNextItem() returns true
TimedLoop::loop([$repositoryAdapter, 'hasNextItem'], $repository, $options);
```

###  Health Score

34

—

LowBetter than 75% of packages

Maintenance58

Moderate activity, may be stable

Popularity4

Limited adoption so far

Community14

Small or concentrated contributor base

Maturity53

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 77.8% 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 ~9 days

Total

2

Last Release

1738d ago

### Community

Maintainers

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

---

Top Contributors

[![MadWillow](https://avatars.githubusercontent.com/u/16151453?v=4)](https://github.com/MadWillow "MadWillow (7 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (1 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (1 commits)")

###  Code Quality

TestsPHPUnit

Code StylePHP CS Fixer

### Embed Badge

![Health badge](/badges/rikta-timed-loop/health.svg)

```
[![Health](https://phpackages.com/badges/rikta-timed-loop/health.svg)](https://phpackages.com/packages/rikta-timed-loop)
```

###  Alternatives

[admad/cakephp-tree

CakPHP plugin for working with tree structures.

11301.4k](/packages/admad-cakephp-tree)[elgentos/vat-switcher

Vat switcher to let customer decide on how to show their prices

1513.0k](/packages/elgentos-vat-switcher)

PHPackages © 2026

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