PHPackages                             gowelle/azure-moderator - 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. gowelle/azure-moderator

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

gowelle/azure-moderator
=======================

Azure Content Moderator wrapper for Laravel

v3.0.0(1mo ago)0273MITPHPPHP ^8.3CI passing

Since May 11Pushed 1mo ago1 watchersCompare

[ Source](https://github.com/gowelle/azure-moderator)[ Packagist](https://packagist.org/packages/gowelle/azure-moderator)[ RSS](/packages/gowelle-azure-moderator/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (20)Versions (14)Used By (0)

Azure Content Safety for Laravel
================================

[](#azure-content-safety-for-laravel)

[![Tests](https://github.com/gowelle/azure-moderator/actions/workflows/test.yml/badge.svg)](https://github.com/gowelle/azure-moderator/actions/workflows/test.yml)[![PHPStan Level 6](https://camo.githubusercontent.com/2761aeebb3945f1ca4e4b0f156a71a3558c10dd6e3da83b1feb44f4d33013329/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048505374616e2d6c6576656c253230362d627269676874677265656e2e737667)](https://phpstan.org/)[![Latest Version on Packagist](https://camo.githubusercontent.com/f9b81960c053ee2d5fac607c9ca0edec6ce88e48a87319e79c1313db19dde7b0/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f676f77656c6c652f617a7572652d6d6f64657261746f722e737667)](https://packagist.org/packages/gowelle/azure-moderator)[![Total Downloads](https://camo.githubusercontent.com/3d545d3e5f4a68a8882ee78a718b93ae38f6f537ca68924d799ef542651e6ae4/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f676f77656c6c652f617a7572652d6d6f64657261746f722e737667)](https://packagist.org/packages/gowelle/azure-moderator)

A Laravel package for content moderation using Azure Content Safety API. This package helps you analyze both text and image content for potentially harmful material, automatically flagging or approving content based on Azure's AI-powered analysis.

---

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

[](#table-of-contents)

- [Features](#features)
- [Requirements](#requirements)
- [Installation](#installation)
- [Configuration](#configuration)
    - [Configuration Options](#configuration-options)
- [Usage](#usage)
    - [Text Moderation](#text-moderation)
    - [Image Moderation](#image-moderation)
    - [Laravel Validation](#laravel-validation)
    - [Error Handling](#error-handling)
    - [Multimodal Analysis (Preview)](#multimodal-analysis-preview)
    - [Multi-Modal Analysis (Batch &amp; Async)](#multi-modal-analysis-batch--async)
    - [Custom Blocklists](#custom-blocklists)
    - [Protected Material Detection](#protected-material-detection)
    - [Artisan Commands](#artisan-commands)
- [Testing](#testing)
    - [Running Tests](#running-tests)
    - [Integration Tests](#integration-tests)
    - [Quality Tools](#quality-tools)
    - [CI/CD](#cicd)
- [Documentation](#documentation)
- [Changelog](#changelog)
- [Contributing](#contributing)
- [Security](#security)
- [Credits](#credits)
- [License](#license)

---

Features
--------

[](#features)

- Easy integration with Azure Content Safety API
- **Text and Image content moderation**
- **Multimodal Analysis (Preview)** - Combined text + image analysis
- **Multi-Modal Analysis (Batch &amp; Async)**
- **Custom Blocklist Management**
- **Protected Material Detection**
- **Strongly-typed DTO responses** (ModerationResult, CategoryAnalysis, MultimodalResult)
- Automatic content analysis and flagging
- Configurable severity thresholds
- User rating support (for text moderation)
- Laravel validation rules for text and images
- Artisan commands for testing &amp; management
- Retry handling for API failures
- **Comprehensive test suite (90+ tests)**
- **Integration tests with real Azure API**
- **PHPStan level 6 static analysis**
- **Performance benchmarks**
- Laravel-native configuration
- Extensive logging

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

[](#requirements)

- PHP 8.3 or higher
- Laravel 11.0 or higher
- Azure Content Safety API subscription

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

[](#installation)

Install the package via composer:

```
composer require gowelle/azure-moderator
```

Publish the configuration file:

```
php artisan vendor:publish --provider="Gowelle\AzureModerator\AzureContentSafetyServiceProvider"
```

Configuration
-------------

[](#configuration)

Add your Azure credentials to your `.env` file:

```
AZURE_CONTENT_SAFETY_ENDPOINT=your-endpoint
AZURE_CONTENT_SAFETY_API_KEY=your-api-key
AZURE_CONTENT_SAFETY_LOW_RATING_THRESHOLD=2
AZURE_CONTENT_SAFETY_HIGH_SEVERITY_THRESHOLD=6
AZURE_MODERATOR_FAIL_ON_ERROR=false
```

### Configuration Options

[](#configuration-options)

- `AZURE_CONTENT_SAFETY_ENDPOINT`: Your Azure Content Safety API endpoint URL
- `AZURE_CONTENT_SAFETY_API_KEY`: Your Azure API key (keep this secure!)
- `AZURE_CONTENT_SAFETY_LOW_RATING_THRESHOLD`: Minimum rating to approve text content (0-5, default: 2)
- `AZURE_CONTENT_SAFETY_HIGH_SEVERITY_THRESHOLD`: Minimum severity to flag content (0-7, default: 3)
- `AZURE_MODERATOR_FAIL_ON_ERROR`: Whether validation should fail when API is unavailable (default: false)

Usage
-----

[](#usage)

### Text Moderation

[](#text-moderation)

#### Basic Usage

[](#basic-usage)

```
use Gowelle\AzureModerator\Facades\AzureModerator;

// Moderate content - returns ModerationResult DTO
$result = AzureModerator::moderate('Some text content', 4.5);

// Check result using DTO methods
if ($result->isApproved()) {
    // Content is safe
} else {
    // Content was flagged
    $reason = $result->reason;
}
```

#### Custom Categories

[](#custom-categories)

```
use Gowelle\AzureModerator\Enums\ContentCategory;

$result = AzureModerator::moderate(
    text: 'Some text content',
    rating: 4.5,
    categories: [
        ContentCategory::HATE->value,
        ContentCategory::VIOLENCE->value
    ]
);
```

### Image Moderation

[](#image-moderation)

#### Basic Image Moderation

[](#basic-image-moderation)

```
use Gowelle\AzureModerator\Facades\AzureModerator;

// Moderate image by URL - returns ModerationResult DTO
$result = AzureModerator::moderateImage('https://example.com/image.jpg');

// Check result using DTO methods
if ($result->isApproved()) {
    // Image is safe
} else {
    // Image was flagged
    $reason = $result->reason;
    $scores = $result->categoriesAnalysis; // Array of CategoryAnalysis DTOs
}
```

#### Base64 Image Moderation

[](#base64-image-moderation)

```
// Moderate uploaded image
$imageData = file_get_contents($uploadedFile->getRealPath());
$base64Image = base64_encode($imageData);

$result = AzureModerator::moderateImage(
    image: $base64Image,
    encoding: 'base64'
);
```

**Note:** Base64 images are limited to 4MB of encoded data, which corresponds to approximately 3MB of original image size (due to base64 encoding overhead of ~33%).

#### Image Moderation with Custom Categories

[](#image-moderation-with-custom-categories)

```
use Gowelle\AzureModerator\Enums\ContentCategory;

$result = AzureModerator::moderateImage(
    image: 'https://example.com/image.jpg',
    categories: [
        ContentCategory::SEXUAL->value,
        ContentCategory::VIOLENCE->value
    ]
);
```

### Laravel Validation

[](#laravel-validation)

Use the `SafeImage` validation rule to automatically validate uploaded images:

```
use Gowelle\AzureModerator\Rules\SafeImage;

// In your form request or controller
$request->validate([
    'avatar' => ['required', 'image', 'max:2048', new SafeImage()],
]);

// With custom categories
$request->validate([
    'profile_picture' => [
        'required',
        'image',
        new SafeImage([
            ContentCategory::SEXUAL->value,
            ContentCategory::VIOLENCE->value
        ])
    ],
]);
```

### Error Handling

[](#error-handling)

The package provides flexible error handling to ensure both security and user experience:

```
use Gowelle\AzureModerator\Exceptions\ModerationException;

try {
    $result = AzureModerator::moderate('Some text content', 4.5);
} catch (ModerationException $e) {
    // Handle API errors (only thrown for input validation errors in moderate())
    Log::error('Moderation failed', [
        'message' => $e->getMessage(),
        'endpoint' => $e->endpoint,
        'status' => $e->statusCode
    ]);
}
```

#### Graceful Degradation and Strict Mode

[](#graceful-degradation-and-strict-mode)

The `fail_on_api_error` configuration controls how the package behaves when the Azure API is unavailable:

**Default Behavior (fail\_on\_api\_error = false):**

- When the Azure API fails or is unavailable, both `moderate()` and `moderateImage()` return approved status
- The `SafeImage` validation rule passes validation, allowing content through
- This prevents blocking users during API outages
- Best for: Production environments prioritizing user experience

**Strict Mode (fail\_on\_api\_error = true):**

- When the Azure API fails, the `SafeImage` validation rule fails with message: "Unable to validate :attribute safety. Please try again."
- Content cannot be moderated until the API is available
- Best for: High-security environments requiring strict content moderation enforcement

**Configuration:**

```
# Default: false (graceful degradation)
AZURE_MODERATOR_FAIL_ON_ERROR=false

# Strict mode: true (fail validation on API errors)
AZURE_MODERATOR_FAIL_ON_ERROR=true
```

**Retry Logic:**The package includes automatic retry logic with exponential backoff for:

- Rate limit errors (429)
- Server errors (500, 503)
- Up to 3 retry attempts per request

### Multimodal Analysis (Preview)

[](#multimodal-analysis-preview)

> ⚠️ **Preview API**: Uses `2024-09-15-preview`. Feature availability varies by Azure region.

Analyze images with associated text for contextual content moderation:

```
use Gowelle\AzureModerator\MultimodalService;

$service = app(MultimodalService::class);

// Analyze image with caption
$result = $service->analyze(
    image: $base64ImageData,
    text: 'User-provided caption',
    encoding: 'base64',
    enableOcr: true
);

if ($result->isFlagged()) {
    echo $result->reason; // "High severity in: Violence"
}
```

#### SafeMultimodal Validation Rule

[](#safemultimodal-validation-rule)

```
use Gowelle\AzureModerator\Rules\SafeMultimodal;

$request->validate([
    'image' => [
        'required',
        'image',
        new SafeMultimodal(
            text: $request->caption,
            categories: ['Sexual', 'Violence']
        )
    ],
]);
```

#### CLI Testing

[](#cli-testing)

```
# Test with URL
php artisan azure-moderator:test-multimodal https://example.com/image.jpg --text="Caption"

# Test with local file
php artisan azure-moderator:test-multimodal ./path/to/image.jpg --local --text="Caption"
```

### Multi-Modal Analysis (Batch &amp; Async)

[](#multi-modal-analysis-batch--async)

Process multiple items or perform context-aware analysis:

```
// Batch Moderation
$results = AzureModerator::moderateBatch([
    ['type' => 'text', 'content' => 'Comment 1', 'rating' => 4.5],
    ['type' => 'image', 'content' => 'https://example.com/img.jpg'],
]);

// Context-Aware (Text + Image)
$result = AzureModerator::moderateWithContext(
    text: 'Check this out!',
    imageUrl: 'https://example.com/meme.jpg',
    rating: 4.0
);
```

For background processing, dispatch the job:

```
use Gowelle\AzureModerator\Jobs\ModerateContentJob;

ModerateContentJob::dispatch(
    contentType: 'text',
    content: 'User bio update',
    rating: 4.5,
    metadata: ['user_id' => 123]
);
```

### Custom Blocklists

[](#custom-blocklists)

Manage custom blocklists to filter specific terms.

```
# Create and manage lists via CLI
php artisan azure-moderator:blocklist create my-list "Banned words"
php artisan azure-moderator:blocklist add-item my-list "forbidden_term"
```

Use in moderation:

```
$result = AzureModerator::moderate(
    text: 'Some text',
    rating: 4.5,
    blocklistNames: ['my-list']
);
```

See [Blocklists Guide](docs/BLOCKLISTS.md) for full details.

### Protected Material Detection

[](#protected-material-detection)

Detect copyrighted content in text:

```
php artisan azure-moderator:test-protected "Lyrics to a song..."
```

Or use the validation rule:

```
use Gowelle\AzureModerator\Rules\SafeText;

$request->validate([
    'content' => ['required', new SafeText()],
]);
```

See [Protected Material Guide](docs/PROTECTED_MATERIAL.md) for details.

### Artisan Commands

[](#artisan-commands)

Test image moderation from the command line:

```
# Test image moderation
php artisan azure-moderator:test-image https://example.com/image.jpg

# Test with specific categories
php artisan azure-moderator:test-image https://example.com/image.jpg --categories=Sexual,Violence
```

Testing
-------

[](#testing)

This package includes a comprehensive test suite with unit tests, integration tests, and performance benchmarks.

### Running Tests

[](#running-tests)

```
# Run unit tests
composer test

# Run integration tests (requires Azure credentials)
composer test:integration

# Run performance benchmarks
composer test:performance

# Run all tests
composer test:all

# Generate coverage report
composer test-coverage
```

### Integration Tests

[](#integration-tests)

Integration tests validate the package against the real Azure Content Safety API. To run them:

1. Copy the example environment file:

    ```
    cp .env.integration.example .env.integration
    ```
2. Add your Azure credentials to `.env.integration`:

    ```
    AZURE_CONTENT_SAFETY_ENDPOINT=https://your-resource.cognitiveservices.azure.com
    AZURE_CONTENT_SAFETY_API_KEY=your-api-key
    ```
3. Run integration tests:

    ```
    composer test:integration
    ```

**Test Coverage:**

- 30+ unit tests
- 50+ integration tests (Azure API)
- 10+ performance benchmarks
- **Total: 90+ tests with 100% pass rate**

See [Integration Testing Guide](docs/INTEGRATION_TESTING.md) for detailed documentation.

### Quality Tools

[](#quality-tools)

```
# Run PHPStan static analysis (level 6)
composer analyse

# Run mutation testing
composer mutate

# Check code style
composer format

# Run all quality checks
composer quality
```

### CI/CD

[](#cicd)

GitHub Actions automatically runs:

- Unit tests (PHP 8.3, 8.4, and 8.5)
- Integration tests (when secrets are configured)
- PHPStan static analysis
- Code style checks

To enable integration tests in CI, add these secrets to your repository:

- `AZURE_CONTENT_SAFETY_ENDPOINT`
- `AZURE_CONTENT_SAFETY_API_KEY`

### Documentation

[](#documentation)

- [Blocklists Guide](docs/BLOCKLISTS.md)
- [Protected Material Guide](docs/PROTECTED_MATERIAL.md)
- [Integration Testing Guide](docs/INTEGRATION_TESTING.md)
- [Performance Testing Guide](docs/PERFORMANCE_TESTING.md)
- [Troubleshooting Guide](docs/TROUBLESHOOTING.md)
- [API Response Examples](docs/API_RESPONSES.md)
- [Roadmap](docs/ROADMAP.md)

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](CONTRIBUTING.md) for details.

Security
--------

[](#security)

If you discover any security related issues, please email  instead of using the issue tracker.

Please review our [Security Policy](SECURITY.md) for more details.

Credits
-------

[](#credits)

- [John Gowelle](https://github.com/gowelle)
- [All Contributors](../../contributors)

License
-------

[](#license)

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

###  Health Score

47

—

FairBetter than 93% of packages

Maintenance96

Actively maintained with recent releases

Popularity12

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity59

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 91.9% 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 ~28 days

Total

12

Last Release

49d ago

Major Versions

v1.3.0 → v2.0.02025-12-17

v2.1.0 → v3.0.02026-03-21

PHP version history (2 changes)v1.0.0PHP ^8.2

v3.0.0PHP ^8.3

### Community

Maintainers

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

---

Top Contributors

[![gowelle](https://avatars.githubusercontent.com/u/87917924?v=4)](https://github.com/gowelle "gowelle (34 commits)")[![cursoragent](https://avatars.githubusercontent.com/u/199161495?v=4)](https://github.com/cursoragent "cursoragent (2 commits)")[![claude](https://avatars.githubusercontent.com/u/81847?v=4)](https://github.com/claude "claude (1 commits)")

---

Tags

contentlaravelmoderationlaravelcontentazuremoderationmoderator

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/gowelle-azure-moderator/health.svg)

```
[![Health](https://phpackages.com/badges/gowelle-azure-moderator/health.svg)](https://phpackages.com/packages/gowelle-azure-moderator)
```

###  Alternatives

[stevebauman/location

Retrieve a user's location by their IP Address

1.3k7.6M65](/packages/stevebauman-location)[bensampo/laravel-embed

Painless responsive embeds for videos, slideshows and more.

142146.8k](/packages/bensampo-laravel-embed)[glhd/conveyor-belt

14797.0k](/packages/glhd-conveyor-belt)[adrianorosa/laravel-geolocation

Laravel Geo Location package to get details for a given IP Address

6593.3k1](/packages/adrianorosa-laravel-geolocation)[bakame/laravel-domain-parser

Laravel package to integrate PHP Domain parser.

26534.8k4](/packages/bakame-laravel-domain-parser)[diego-ninja/sentinel

A content moderation and sentiment analysis library for Laravel 10+

384.3k](/packages/diego-ninja-sentinel)

PHPackages © 2026

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