PHPackages                             laragear/attempt-once - 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. laragear/attempt-once

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

laragear/attempt-once
=====================

Run and manage callbacks across multiple app instances

v1.0.0(5mo ago)10[3 PRs](https://github.com/Laragear/AttemptOnce/pulls)MITPHPPHP ^8.4CI passing

Since Jan 15Pushed 4mo agoCompare

[ Source](https://github.com/Laragear/AttemptOnce)[ Packagist](https://packagist.org/packages/laragear/attempt-once)[ Fund](https://github.com/sponsors/DarkGhostHunter)[ Fund](https://paypal.me/darkghosthunter)[ RSS](/packages/laragear-attempt-once/feed)WikiDiscussions 1.x Synced today

READMEChangelog (1)Dependencies (4)Versions (5)Used By (0)

Deprecated
==========

[](#deprecated)

Use [`Cache::funnel()`](https://github.com/laravel/framework/pull/58439) with 1 attempt instead.

Once
====

[](#once)

[![Latest Version on Packagist](https://camo.githubusercontent.com/03ca31d14d17dee9155741e360f94633575bd561afbc7d7b2b041a14e3c498df/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6c617261676561722f617474656d70742d6f6e63652e737667)](https://packagist.org/packages/laragear/attempt-once)[![Latest stable test run](https://github.com/Laragear/AttemptOnce/actions/workflows/php.yml/badge.svg?branch=1.x)](https://github.com/Laragear/AttemptOnce/actions/workflows/php.yml)[![Codecov coverage](https://camo.githubusercontent.com/1a155168b28b38da4ca4b48f6cf24251b129874ed4f7ee0b50ea3449ca85d6b8/68747470733a2f2f636f6465636f762e696f2f67682f4c617261676561722f417474656d70744f6e63652f6272616e63682f312e782f67726170682f62616467652e7376673f746f6b656e3d49386331684742747163)](https://codecov.io/gh/Laragear/AttemptOnce)[![Maintainability](https://camo.githubusercontent.com/7bcb3dcd1ce3cc9320d04565ec5e72491ad5f801eecfcf7360193624f40af31b/68747470733a2f2f716c74792e73682f67682f4c617261676561722f70726f6a656374732f417474656d70744f6e63652f6d61696e7461696e6162696c6974792e737667)](https://qlty.sh/gh/Laragear/projects/AttemptOnce)[![Sonarcloud Status](https://camo.githubusercontent.com/6b59a7cda58a72c0034ed6f21d1b07c86fd0c834537ae0cadbb267e95f6be39a/68747470733a2f2f736f6e6172636c6f75642e696f2f6170692f70726f6a6563745f6261646765732f6d6561737572653f70726f6a6563743d4c617261676561725f417474656d70744f6e6365266d65747269633d616c6572745f737461747573)](https://sonarcloud.io/dashboard?id=Laragear_AttemptOnce)[![Laravel Octane Compatibility](https://camo.githubusercontent.com/70359a356da237cd29561bc5d0bb80baae775b5ff62f288ed324755382858342/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2532304f6374616e652d436f6d70617469626c652d737563636573733f7374796c653d666c6174266c6f676f3d6c61726176656c)](https://laravel.com/docs/12.x/octane#introduction)

Run and manage callbacks across multiple app instances, atomically.

```
use App\Mails\Newsletter;

attempt_once(function () => {
    Newsletter::send();
});
```

Become a sponsor
----------------

[](#become-a-sponsor)

[![](.github/assets/support.png)](https://github.com/sponsors/DarkGhostHunter)

Your support allows me to keep this package free, up-to-date and maintainable.

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

[](#requirements)

- PHP 8.4
- Laravel 11 or later

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

[](#installation)

You can install the package via Composer.

```
composer require laragear/once
```

How does this work?
-------------------

[](#how-does-this-work)

It uses Laravel's Rate Limiter behind the scenes to allow callbacks to run once. This way all app instances are *aware* of the callback execution, ensuring only runs once inside a given window of time, which is 1 minute by default.

Usage
-----

[](#usage)

The simplest way to use `attempt_once()` is to just issue a callback, which will be executed only once for 30 seconds. A key will be computed from the callback as `laragear|attempt_once:{hash}` based on the callback unique position in your application.

```
attempt_once(function () {
    // ... do something.
})
```

Adding a second argument after the callback will set the amount of time to "hold" the execution. You may use a `DateTimeInterface` instance, a `DateInterval` object or just an amount of seconds.

```
attempt_once(function () {
    // ... do something.
}, now()->addMinute())
```

Important

When using a single callback, the hash computed takes into account the place where is called. Duplicating the code **will make both callbacks hashes different**, even if they do exactly the same.

While the above may suffice for most simple scenarios, you may have more granular control on the execution by calling `attempt_once()` with a key to identify the execution, or a string backed enum. You will receive a builder instance to configure how to run it:

```
$result = attempt_once('send-email')->in(60)->run(function () {
    // ...
});

use App\Enums\EmailType;

$result = attempt_once(EmailType::Transactional)->in(60)->run(function () {
    // ...
});
```

### Custom key

[](#custom-key)

The `attempt_once()` method allows to identify the callback to run once with a simple string. With a constant string, you may [check the execution status elsewhere in your app](#checking-execution).

```
attempt_once('send-email')->run(function () {
    // ...
});
```

You can issue multiple strings or arrays, which is great when you need to separate executions programmatically. The resulting key will be concatenated using `|`. If you pass an array, the key and value will be concatenated as `{key}:{value}`.

```
// "send-email|transaction|user:1"
attempt_once('send-email', 'transaction', ['user' => 1])->run(function () {
    // ...
});
```

If you pass an Eloquent Model as second parameter, it will be used to identify the callback as `{class}:{key}`, essentially making the callback unique for each model you pass.

```
use App\Models\User;

$user = User::find(1);

// "send-email|\App\Models\User:1"
attempt_once('send-email', $user)->run(function () {
    // ...
});
```

When using an Enum as key, the class name and case name will be used as part of the key as `{class}:{case}`.

```
use App\Models\User;
use App\Enums\EmailType;

$user = User::find(1);

// "send-email|\App\Enums\EmailType:Transactional|\App\Models\User:1"
attempt_once('send-email', EmailType::Transactional)->run(function () {
    // ...
});
```

### Time

[](#time)

You may change the window of time using `for()` with the amount of seconds. You may also use `DateTimeInterface` instance, or a `DateInterval` instance.

```
use function Illuminate\Support\seconds;

// Using seconds
attempt_once('send-email')->for(30)->run(function () {
    // ...
});

// Using a DateTimeInterface, like a Carbon instance
attempt_once('send-email')->for(now()->addSeconds(30))->run(function () {
    // ...
});

// Using a DateInterval, like the `seconds()` helper.
attempt_once('send-email')->for(seconds(30))->run(function () {
    // ...
});
```

Important

You *may* change the window of time programmatically, but consider that only previous successful execution will set the time. Since subsequent executions won't run, the time won't be updated.

Callback result
---------------

[](#callback-result)

When the callback runs, its result will be returned. When the callback does not run because it's rate limited, `false` will be returned.

```
use App\Models\Article;
use Illuminate\Support\Facades\Route;

Route::get('/articles/all', function () {
    $articles = attempt_once(function () {
        return Article::limit(10)->latest()->get();
    });

    // Check the callback was not executed
    if ($articles === false) {
        return 'You need to wait 30 seconds to retrieve more articles';
    }

    return $articles;
});
```

### Default result

[](#default-result)

Sometimes you will want to return another value rather than `false` if the callback is not executed. For that, use the `or()` method.

```
use App\Models\Article;
use function Illuminate\Support\minutes;

$collection = attempt_once('latest-articles')
    ->or(new Collection())
    ->run(function () {
        return Article::limit(10)->latest()->get();
    });
```

### Checking execution

[](#checking-execution)

To check if the callback was executed, you may use the `wasExecuted()` and `wasNotExecuted()` methods, which is only accessible using a named key.

```
if (attempt_once('send-email')->wasExecuted()) {
    return 'An email was already sent!';
}

if (attempt_once('send-email')->wasNotExecuted()) {
    return 'You can send a new email now';
}
```

To check how many seconds remain to execute the callback again, use `availableIn()`, or `readyAt()` to get a Carbon instance.

```
$seconds = attempt_once('send-email')->availableIn();

echo "You can send a new email in $seconds seconds.";

$datetime = attempt_once('send-email')->readyAt();

echo "You can send a new email at $datetime."
```

### Cache Store

[](#cache-store)

By default, Laravel's Rate Limiter uses the application default cache store. If you want to change the cache store to use, [configure the Rate Limiter in your app configuration](https://laravel.com/docs/12.x/rate-limiting#cache-configuration).

Laravel Octane compatibility
----------------------------

[](#laravel-octane-compatibility)

- There are no singletons using a stale app instance.
- There are no singletons using a stale config instance.
- There are no singletons using a stale request instance.
- There are no static properties written during a request.

There should be no problems using this package with Laravel Octane.

Security
--------

[](#security)

If you discover any security-related issues, issue a [Security Advisory](https://github.com/Laragear/Once/security/advisories/new).

License
=======

[](#license)

This specific package version is licensed under the terms of the [MIT License](LICENSE.md), at the time of publishing.

[Laravel](https://laravel.com) is a Trademark of [Taylor Otwell](https://github.com/TaylorOtwell/). Copyright © 2011-2026 Laravel LLC.

###  Health Score

37

—

LowBetter than 81% of packages

Maintenance74

Regular maintenance activity

Popularity2

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity55

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

Total

2

Last Release

120d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/5141911?v=4)[Italo](/maintainers/DarkGhostHunter)[@DarkGhostHunter](https://github.com/DarkGhostHunter)

---

Top Contributors

[![DarkGhostHunter](https://avatars.githubusercontent.com/u/5141911?v=4)](https://github.com/DarkGhostHunter "DarkGhostHunter (11 commits)")

### Embed Badge

![Health badge](/badges/laragear-attempt-once/health.svg)

```
[![Health](https://phpackages.com/badges/laragear-attempt-once/health.svg)](https://phpackages.com/packages/laragear-attempt-once)
```

###  Alternatives

[laragear/two-factor

On-premises 2FA Authentication for out-of-the-box.

341942.8k18](/packages/laragear-two-factor)[kirschbaum-development/commentions

A package to allow you to create comments, tag users and more

149129.0k](/packages/kirschbaum-development-commentions)[bramdeleeuw/cookieconsent

GDPR compliant cookie bar and consent checker

1511.7k2](/packages/bramdeleeuw-cookieconsent)[voodoophp/paginator

Paginator is a simple class that allows you to create pagination. It doesn't require any database connection. It is compatible with Twitter's Bootstrap Framework, by using the CSS class pagination that is also attached.

351.5k1](/packages/voodoophp-paginator)

PHPackages © 2026

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