PHPackages                             mchev/banhammer - 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. [Security](/categories/security)
4. /
5. mchev/banhammer

ActiveLibrary[Security](/categories/security)

mchev/banhammer
===============

Banhammer for Laravel allows you to ban any Model by key and by IP.

v2.5.0(3mo ago)372111.7k↓48.4%282MITPHPPHP ^8.0CI passing

Since Feb 11Pushed 3mo ago2 watchersCompare

[ Source](https://github.com/mchev/banhammer)[ Packagist](https://packagist.org/packages/mchev/banhammer)[ Docs](https://github.com/mchev/banhammer)[ GitHub Sponsors](https://github.com/mchev)[ RSS](/packages/mchev-banhammer/feed)WikiDiscussions 2.x Synced 3d ago

READMEChangelog (10)Dependencies (11)Versions (24)Used By (2)

Banhammer 🔨
===========

[](#banhammer-)

> A simple and powerful ban package for Laravel - ban models, IPs, and countries with ease.

[![Latest Version on Packagist](https://camo.githubusercontent.com/e49924bb79b059f66bed6b63185e15a61b4ac8c2cd675c21cb60fb6fc7210774/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6d636865762f62616e68616d6d65722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/mchev/banhammer)[![GitHub Tests Action Status](https://github.com/mchev/banhammer/actions/workflows/run-tests.yml/badge.svg)](https://github.com/mchev/banhammer/actions/workflows/run-tests.yml)[![Total Downloads](https://camo.githubusercontent.com/d97d2e2b4341906fb3f8c7676a6497735a633cdb1b689bb1822ca10eb92a13c8/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6d636865762f62616e68616d6d65722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/mchev/banhammer)[![Package for laravel](https://camo.githubusercontent.com/236bdc6baa59bc38274092110f30505ea78b0df6d88e2eec7b15da73b6141427/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5061636b616765253230666f722532304c61726176656c2d677265792e7376673f7374796c653d666c61742d737175617265266c6f676f3d6c61726176656c266c6f676f436f6c6f723d7768697465)](https://packagist.org/packages/mchev/banhammer)

Banhammer allows you to ban any Eloquent model, IP addresses, and even entire countries. Bans can be permanent or temporary with automatic expiration.

---

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

[](#-table-of-contents)

- [Quick Start](#-quick-start)
- [Features](#-features)
- [Installation](#-installation)
- [Usage Guide](#-usage-guide)
    - [Banning Models](#banning-models)
    - [Banning IPs](#banning-ips)
    - [Country Blocking](#country-blocking)
    - [Middleware](#middleware)
    - [Scheduler](#scheduler)
    - [Events](#events)
- [Advanced Topics](#-advanced-topics)
    - [Metas](#metas)
    - [UUIDs](#uuids)
    - [Upgrading](#upgrading-to-20-from-1x)
- [Development](#-development)

---

🚀 Quick Start
-------------

[](#-quick-start)

```
composer require mchev/banhammer
php artisan vendor:publish --provider="Mchev\Banhammer\BanhammerServiceProvider" --tag="migrations"
php artisan migrate
```

Add the trait to your model:

```
use Mchev\Banhammer\Traits\Bannable;

class User extends Model
{
    use Bannable;
}
```

Ban a user:

```
$user->ban();
```

---

✨ Features
----------

[](#-features)

- ✅ Ban any Eloquent model (User, Team, etc.)
- ✅ Ban IP addresses (single or multiple)
- ✅ Block entire countries
- ✅ Temporary or permanent bans
- ✅ Automatic expiration handling
- ✅ Middleware protection
- ✅ Event system
- ✅ Metadata support

---

📦 Installation
--------------

[](#-installation)

### Requirements

[](#requirements)

- PHP 8.0+

### Laravel compatibility

[](#laravel-compatibility)

LaravelSupported since Banhammer9.xv1.0.010.xv1.0.011.xv2.2.012.xv2.4.013.xv2.5.0### Setup

[](#setup)

1. **Install the package:**

    ```
    composer require mchev/banhammer
    ```
2. **Publish and run migrations:**

    ```
    php artisan vendor:publish --provider="Mchev\Banhammer\BanhammerServiceProvider" --tag="migrations"
    php artisan migrate
    ```
3. **Publish config (optional):**

    ```
    php artisan vendor:publish --provider="Mchev\Banhammer\BanhammerServiceProvider" --tag="config"
    ```

    > 💡 The config file allows you to customize table name, model, fallback URLs, and more.

---

📖 Usage Guide
-------------

[](#-usage-guide)

### Banning Models

[](#banning-models)

#### Make a Model Bannable

[](#make-a-model-bannable)

Add the `Bannable` trait to any model:

```
use Mchev\Banhammer\Traits\Bannable;

class User extends Model
{
    use Bannable;
}
```

> 💡 You can add the trait to multiple models (User, Team, Group, etc.)

#### Basic Operations

[](#basic-operations)

ActionCode**Ban a user**`$user->ban()`**Ban with expiration**`$user->banUntil('2 days')`**Check if banned**`$user->isBanned()`**Check if not banned**`$user->isNotBanned()`**Unban**`$user->unban()`#### Advanced Ban Options

[](#advanced-ban-options)

```
$user->ban([
    'comment' => "You've been evil",
    'ip' => "8.8.8.8",
    'expired_at' => Carbon::now()->addDays(7),
    'created_by_type' => 'App\Models\Admin',
    'created_by_id' => auth()->id(),
    'metas' => [
        'route' => request()->route()->getName(),
        'user_agent' => request()->header('user-agent')
    ]
]);
```

> ⚠️ Without `expired_at`, the ban is permanent.

#### Query Scopes

[](#query-scopes)

```
// Get banned users
$bannedUsers = User::banned()->get();

// Get non-banned users
$activeUsers = User::notBanned()->get();

// Alternative syntax
$activeUsers = User::banned(false)->get();
```

#### List Bans

[](#list-bans)

```
// All bans for a model
$bans = $user->bans()->get();

// Only expired bans
$expired = $user->bans()->expired()->get();

// Active bans
$active = $user->bans()->notExpired()->get();
```

---

### Banning IPs

[](#banning-ips)

#### Basic Operations

[](#basic-operations-1)

```
use Mchev\Banhammer\IP;

// Ban single IP
IP::ban("8.8.8.8");

// Ban multiple IPs
IP::ban(["8.8.8.8", "4.4.4.4", "1.1.1.1"]);

// Ban with expiration
IP::ban("8.8.8.8", [], now()->addMinutes(10));

// Ban with metadata
IP::ban("8.8.8.8", [
    'reason' => 'spam',
    'severity' => 'high'
]);
```

#### Unban IPs

[](#unban-ips)

```
// Unban single IP
IP::unban("8.8.8.8");

// Unban multiple IPs
IP::unban(["8.8.8.8", "4.4.4.4"]);
```

#### Check &amp; List Banned IPs

[](#check--list-banned-ips)

```
// Check if IP is banned
IP::isBanned("8.8.8.8"); // bool

// Get all banned IPs
$ips = IP::banned()->get(); // Collection
$ips = IP::banned()->pluck('ip')->toArray(); // Array
```

---

### Country Blocking

[](#country-blocking)

Block access from specific countries automatically.

#### Configuration

[](#configuration)

1. **Enable country blocking** in `config/ban.php`:

    ```
    'block_by_country' => true,
    ```
2. **Specify blocked countries**:

    ```
    'blocked_countries' => ['FR', 'ES', 'US'],
    ```

That's it! The middleware will automatically block requests from these countries.

> ⚠️ **Rate Limit Notice:** The free version of ip-api.com has a limit of 45 requests/minute. Exceeding this will result in 429 errors until the limit resets.

> 💡 **Want to improve this?** If you have suggestions for better geolocation services or want to contribute improvements, please [open an issue](https://github.com/mchev/banhammer/issues) or submit a [pull request](https://github.com/mchev/banhammer/pulls).

---

### Middleware

[](#middleware)

Protect your routes with ban middleware:

#### Available Middleware

[](#available-middleware)

MiddlewareDescription`auth.banned`Blocks banned users`ip.banned`Blocks banned IPs`logout.banned`Logs out and blocks banned users/IPs#### Usage

[](#usage)

```
// Single route
Route::get('/dashboard', [DashboardController::class, 'index'])
    ->middleware('auth.banned');

// Route group
Route::middleware(['auth.banned'])->group(function () {
    Route::get('/profile', [ProfileController::class, 'index']);
    Route::get('/settings', [SettingsController::class, 'index']);
});

// Block IPs on all routes
// Add to app/Http/Kernel.php:
protected $middleware = [
    // ...
    \Mchev\Banhammer\Middleware\IPBanned::class,
];
```

> 💡 **Tip:** `logout.banned` includes the functionality of both `auth.banned` and `ip.banned`, so you don't need to use them together.

---

### Scheduler

[](#scheduler)

Banhammer automatically deletes expired bans using Laravel's scheduler.

#### Setup

[](#setup-1)

> ⚠️ **Important:** You must have a cron job running Laravel's scheduler:
>
> ```
> * * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
> ```
>
>
>
> See: [Laravel Scheduler Docs](https://laravel.com/docs/scheduling#running-the-scheduler)

#### Configuration

[](#configuration-1)

By default, the `banhammer:unban` command runs **every minute**. You can customize this:

**Disable automatic scheduler:**

```
// config/ban.php
'scheduler_enabled' => false,
```

Or via environment:

```
BANHAMMER_SCHEDULER_ENABLED=false
```

**Change frequency:**

```
// config/ban.php
'scheduler_periodicity' => 'everyFiveMinutes', // or 'hourly', 'daily', etc.
```

Or via environment:

```
BANHAMMER_SCHEDULER_PERIODICITY=everyFiveMinutes
```

**Available frequencies:** `everyMinute`, `everyFiveMinutes`, `everyTenMinutes`, `everyFifteenMinutes`, `everyThirtyMinutes`, `hourly`, `daily`, `twiceDaily`, etc.

---

### Events

[](#events)

Listen to ban/unban events:

```
use Mchev\Banhammer\Events\ModelWasBanned;
use Mchev\Banhammer\Events\ModelWasUnbanned;

Event::listen(ModelWasBanned::class, function ($event) {
    // User was banned
    Log::info("User {$event->ban->bannable->id} was banned");
});

Event::listen(ModelWasUnbanned::class, function ($event) {
    // User was unbanned
    Log::info("User {$event->ban->bannable->id} was unbanned");
});
```

---

🔧 Advanced Topics
-----------------

[](#-advanced-topics)

### Metas

[](#metas)

Store additional data with bans:

```
// Set meta
$ban->setMeta('username', 'Jane');
$ban->setMeta('reason', 'spam');

// Get meta
$ban->getMeta('username'); // 'Jane'

// Check if meta exists
$ban->hasMeta('username'); // true

// Remove meta
$ban->forgetMeta('username');
```

#### Filter by Meta

[](#filter-by-meta)

```
// Find bans with specific meta
IP::banned()->whereMeta('username', 'Jane')->get();
$user->bans()->whereMeta('reason', 'spam')->get();
User::whereBansMeta('username', 'Jane')->get();
```

#### Ban with Metas

[](#ban-with-metas)

```
// When banning
$user->ban([
    'metas' => [
        'route' => request()->route()->getName(),
        'user_agent' => request()->header('user-agent')
    ]
]);

IP::ban("8.8.8.8", [
    'reason' => 'spam',
    'severity' => 'high'
]);
```

---

### UUIDs

[](#uuids)

To use UUIDs instead of auto-incrementing IDs:

1. **Publish migrations:**

    ```
    php artisan vendor:publish --provider="Mchev\Banhammer\BanhammerServiceProvider" --tag="migrations"
    ```
2. **Edit the migration:**

    ```
    - $table->id();
    + $table->uuid('id');
    ```
3. **Create a custom Ban model:**

    ```
    namespace App\Models;

    use Illuminate\Database\Eloquent\Concerns\HasUuids;
    use Mchev\Banhammer\Models\Ban as BanhammerBan;

    class Ban extends BanhammerBan
    {
        use HasUuids;
    }
    ```
4. **Update config:**

    ```
    // config/ban.php
    'model' => \App\Models\Ban::class,
    ```

---

### Upgrading To 2.0 from 1.x

[](#upgrading-to-20-from-1x)

1. **Update composer.json:**

    ```
    "require": {
        "mchev/banhammer": "^2.0"
    }
    ```
2. **Update the package:**

    ```
    composer update mchev/banhammer
    ```
3. **Update configuration:**

    ```
    # Backup your current config
    cp config/ban.php config/ban.php.backup

    # Republish config
    php artisan vendor:publish --provider="Mchev\Banhammer\BanhammerServiceProvider" --tag="config" --force

    # Review and merge any custom settings
    ```

---

🛠️ Development
--------------

[](#️-development)

### Commands

[](#commands)

```
# Manually delete expired bans
php artisan banhammer:unban

# Permanently delete all expired bans
php artisan banhammer:clear
```

### Programmatic Usage

[](#programmatic-usage)

```
use Mchev\Banhammer\Banhammer;

// Delete expired bans
Banhammer::unbanExpired();

// Permanently delete expired bans
Banhammer::clear();
```

### Testing

[](#testing)

```
composer test
```

---

🤝 Contributing
--------------

[](#-contributing)

We welcome contributions! Please:

- Open issues for bug reports or feature requests
- Submit pull requests (mark as "ready for review")
- Ensure all tests pass
- Follow Laravel coding standards

> 💡 Pull requests in "draft" state will be closed after a few days of inactivity.

---

🙏 Credits
---------

[](#-credits)

Inspired by [laravel-ban](https://github.com/cybercog/laravel-ban) from [cybercog](https://github.com/cybercog).

---

📄 License
---------

[](#-license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

58

—

FairBetter than 98% of packages

Maintenance82

Actively maintained with recent releases

Popularity52

Moderate usage in the ecosystem

Community23

Small or concentrated contributor base

Maturity60

Established project with proven stability

 Bus Factor1

Top contributor holds 93.1% 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 ~54 days

Recently: every ~68 days

Total

22

Last Release

96d ago

Major Versions

v1.x-dev → v2.0.02024-01-07

### Community

Maintainers

![](https://www.gravatar.com/avatar/1a4fc05da542c49e0d7d3aa2bd8c077c80c502ad2beeee5da4d5ed398e5de296?d=identicon)[mchev](/maintainers/mchev)

---

Top Contributors

[![mchev](https://avatars.githubusercontent.com/u/5514329?v=4)](https://github.com/mchev "mchev (149 commits)")[![KieranLProctor](https://avatars.githubusercontent.com/u/25559341?v=4)](https://github.com/KieranLProctor "KieranLProctor (4 commits)")[![mepsd](https://avatars.githubusercontent.com/u/45997529?v=4)](https://github.com/mepsd "mepsd (3 commits)")[![onlime](https://avatars.githubusercontent.com/u/2759561?v=4)](https://github.com/onlime "onlime (2 commits)")[![dannydinges](https://avatars.githubusercontent.com/u/1787211?v=4)](https://github.com/dannydinges "dannydinges (1 commits)")[![YazeedAlsaif](https://avatars.githubusercontent.com/u/3579831?v=4)](https://github.com/YazeedAlsaif "YazeedAlsaif (1 commits)")

---

Tags

accessautorizationbanblockcountriesiplaravelmiddlewarepackagephprestrictsecuritytraituserlaravelIPcountrybanbannablemchevbans-for-laravel

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/mchev-banhammer/health.svg)

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

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3355.3M346](/packages/psalm-plugin-laravel)[laravel/pulse

Laravel Pulse is a real-time application performance monitoring tool and dashboard for your Laravel application.

1.7k15.1M132](/packages/laravel-pulse)[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9762.4M131](/packages/roots-acorn)[laravel/cashier

Laravel Cashier provides an expressive, fluent interface to Stripe's subscription billing services.

2.6k29.9M146](/packages/laravel-cashier)[laravel/mcp

Rapidly build MCP servers for your Laravel applications.

77022.3M151](/packages/laravel-mcp)[api-platform/laravel

API Platform support for Laravel

58171.6k14](/packages/api-platform-laravel)

PHPackages © 2026

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