PHPackages                             tanthammar/laravel-extras - 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. [Validation &amp; Sanitization](/categories/validation)
4. /
5. tanthammar/laravel-extras

ActiveLibrary[Validation &amp; Sanitization](/categories/validation)

tanthammar/laravel-extras
=========================

Custom validation rules for the Laravel Framework

4.2.0(6mo ago)31.5k—0%1MITPHPPHP ^8.3|^8.4

Since Nov 16Pushed 6mo ago1 watchersCompare

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

READMEChangelog (10)Dependencies (2)Versions (30)Used By (1)

Helpers and Macros for Laravel
==============================

[](#helpers-and-macros-for-laravel)

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

[](#requirements)

- PHP 8.3+
- Laravel v11.0+
- MySQL or PostgreSQL database (for builder macros using raw SQL)

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

[](#installation)

```
composer require tanthammar/laravel-extras
```

Migration Setup
---------------

[](#migration-setup)

This package publishes a migration file for the `ocr_numbers` table, used to ensure cross-table uniqueness of OCR numbers.

```
php artisan vendor:publish --provider="TantHammar\LaravelExtras\LaravelExtrasServiceProvider" --tag="migrations"
php artisan migrate
```

Query Builder Macros
--------------------

[](#query-builder-macros)

### Search and Filter Macros

[](#search-and-filter-macros)

#### whereStartsWith / orWhereStartsWith

[](#wherestartswith--orwherestartswith)

Case-insensitive prefix matching:

```
// Find users whose email starts with 'john'
User::whereStartsWith('email', 'john')->get();

// Chain with other conditions
User::where('active', true)->orWhereStartsWith('name', 'admin')->get();
```

#### whereEndsWith / orWhereEndsWith

[](#whereendswith--orwhereendswith)

Case-insensitive suffix matching:

```
// Find users with gmail addresses
User::whereEndsWith('email', 'gmail.com')->get();
```

#### whereAllLike

[](#wherealllike)

Search multiple columns where ALL must match:

```
// Find users where BOTH name and email contain 'john'
User::whereAllLike(['name', 'email'], 'john')->get();
```

#### orWhereAnyLike

[](#orwhereanylike)

Search multiple columns where ANY can match:

```
// Find users where name OR email contains 'john'
User::where('active', true)->orWhereAnyLike(['name', 'email'], 'john')->get();
```

#### whereContains / orWhereContains

[](#wherecontains--orwherecontains)

Space-separated word searching:

```
// Find users where name contains both 'john' AND 'doe' (in any order)
User::whereContains('name', 'john doe')->get();

// OR condition with contains
User::where('active', true)->orWhereContains(['name', 'email'], 'john doe')->get();
```

#### whereRelationsLike

[](#whererelationslike)

Search across model relationships:

```
// Search posts by content, title, or author name
Post::whereRelationsLike(['title', 'content', 'author.name'], 'laravel')->get();
```

### Translatable Content Macros

[](#translatable-content-macros)

#### whereTranslatableStartsWith / orWhereTranslatableStartsWith

[](#wheretranslatablestartswith--orwheretranslatablestartswith)

Search JSON translation columns:

```
// Find events where localized name starts with 'Summer'
Event::whereTranslatableStartsWith('name', 'Summer')->get();

// Search specific locale
Event::whereTranslatableStartsWith('name', 'Été', 'fr')->get();
```

#### whereTranslatableLike / orWhereTranslatableLike

[](#wheretranslatablelike--orwheretranslatablelike)

```
// Find events where localized name contains 'festival'
Event::whereTranslatableLike('name', 'festival')->get();
```

#### whereTranslatableContains / orWhereTranslatableContains

[](#wheretranslatablecontains--orwheretranslatablecontains)

```
// Find events where localized name contains 'music festival' (both words)
Event::whereTranslatableContains('name', 'music festival')->get();
```

### Utility Macros

[](#utility-macros)

#### whereOverlaps

[](#whereoverlaps)

Find overlapping date ranges:

```
// Find bookings that overlap with a specific date range
Booking::whereOverlaps('start_date', 'end_date', '2024-01-01', '2024-01-31')->get();
```

#### existsById / existsByUuid

[](#existsbyid--existsbyuuid)

Quick existence checks:

```
// Check if user exists by ID
if (User::existsById(123)) {
    // User exists
}

// Check if record exists by UUID
if (Product::existsByUuid('550e8400-e29b-41d4-a716-446655440000')) {
    // Product exists
}
```

#### orderByTranslation / orderByLocale

[](#orderbytranslation--orderbylocale)

Locale-aware sorting:

```
// Sort by translated name field
Event::orderByTranslation('name', 'asc')->get();

// Sort by regular field with locale collation
User::orderByLocale('name', 'desc')->get();
```

Helper Classes
--------------

[](#helper-classes)

### String and Text Processing

[](#string-and-text-processing)

#### CleanNumber

[](#cleannumber)

Remove all non-numeric characters:

```
use TantHammar\LaravelExtras\CleanNumber;

$phone = CleanNumber::clean('+46 (0)70-123 45 67');
// Result: '46701234567'
```

#### NoWhiteSpace

[](#nowhitespace)

Remove all whitespace characters:

```
use TantHammar\LaravelExtras\NoWhiteSpace;

$clean = NoWhiteSpace::clean("Hello\n\tWorld   ");
// Result: 'HelloWorld'
```

#### MarkdownToHtmlString

[](#markdowntohtmlstring)

Convert Markdown to HTML:

```
use TantHammar\LaravelExtras\MarkdownToHtmlString;

$html = new MarkdownToHtmlString('**Bold text** with [link](https://example.com)');
// Use in Blade templates
{!! $html !!}

// Filament placeholder field example
Placeholder::make(trans('fields.accounting-chart'))
    ->disableLabel()
    ->content(new MarkdownToHtmlString(__('fields.account_hint')))
    ->columnSpan('full')
```

### Data Manipulation

[](#data-manipulation)

#### Array Helper

[](#array-helper)

```
use TantHammar\LaravelExtras\ArrHelper;

// Remove empty values from array
$clean = ArrHelper::filledOnly(['name' => 'John', 'email' => '', 'age' => null]);
// Result: ['name' => 'John']

// Swap array items (using Arr::swap macro)
$assocArray = [
    'item_one'   => ['name' => 'One'],
    'item_two'   => ['name' => 'Two'],
    'item_three' => ['name' => 'Three'],
    'item_four'  => ['name' => 'Four'],
];

$newArray = Arr::swap($assocArray, 'item_one', 'item_three');
/*
 * Result:
 * [
 *     'item_three' => ['name' => 'Three'],
 *     'item_two'   => ['name' => 'Two'],
 *     'item_one'   => ['name' => 'One'],
 *     'item_four'  => ['name' => 'Four'],
 * ]
 */
```

#### Money Integer Cast

[](#money-integer-cast)

Store monetary values as integers:

```
use TantHammar\LaravelExtras\MoneyIntegerCast;

class Product extends Model
{
    protected $casts = [
        'price' => MoneyIntegerCast::class,
    ];
}

// Store $19.99 as 1999 (integer)
$product = new Product();
$product->price = 19.99;  // Stored as 1999
echo $product->price;     // Outputs: 19.99
```

### Specialized Utilities

[](#specialized-utilities)

#### OCR3 (Swedish Bank References)

[](#ocr3-swedish-bank-references)

Generate OCR numbers with Luhn algorithm:

```
use TantHammar\LaravelExtras\OCR3;

// Generate unique OCR number
$ocr = OCR3::unique();
// Result: '1234567890' (with valid check digit)

// Generate with specific length
$ocr = OCR3::unique(8);
// Result: '12345678' (8 digits with check digit)

// Use in factories
$factory->define(Invoice::class, function (Faker $faker) {
    return [
        'ocr_number' => $faker->ocr3(),
    ];
});
```

#### SKU Generator

[](#sku-generator)

Generate product SKUs:

```
use TantHammar\LaravelExtras\SKU;

$sku = SKU::generate('Premium Widget');
// Result: 'PW-ABC123' (source prefix + random signature)
```

### Debug Utilities

[](#debug-utilities)

#### PrettyPrint

[](#prettyprint)

Formatted debugging output:

```
use TantHammar\LaravelExtras\PrettyPrint;

// In PHP
PrettyPrint::dump($complexArray);

// In Blade templates
@prettyPrint($data)
```

Breaking Changes from Previous Versions
---------------------------------------

[](#breaking-changes-from-previous-versions)

### Query Macro Renames (v4.0+)

[](#query-macro-renames-v40)

- `whereLike()` → `whereAllLike()`
- `orWhereLike()` → `orWhereAnyLike()`

### Version Requirements (v4.0+)

[](#version-requirements-v40)

- Minimum PHP version: 8.3+ (was 8.1+)
- Minimum Laravel version: 11.0+ (was 9.0+)

### Implementation Changes (v4.0+)

[](#implementation-changes-v40)

- All query macros now use Laravel's native `whereLike()` method with `caseSensitive: false`
- Removed custom database operator detection in favor of Laravel's built-in handling
- Improved query logic for proper OR condition chaining

###  Health Score

47

—

FairBetter than 94% of packages

Maintenance67

Regular maintenance activity

Popularity22

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity74

Established project with proven stability

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

Total

29

Last Release

207d ago

Major Versions

1.3.0 → 2.0.02023-07-26

2.2.0 → 3.0.02024-09-24

3.6.0 → 4.02025-07-15

PHP version history (5 changes)1.0PHP ^8.1

1.2.0PHP ^8.1|^8.2

2.1.0PHP ^8.1|^8.2|^8.3

3.1PHP ^8.1|^8.2|^8.3|^8.4

4.0PHP ^8.3|^8.4

### Community

Maintainers

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

---

Top Contributors

[![tanthammar](https://avatars.githubusercontent.com/u/21239634?v=4)](https://github.com/tanthammar "tanthammar (44 commits)")

---

Tags

laravelvalidationrulestanthammar

### Embed Badge

![Health badge](/badges/tanthammar-laravel-extras/health.svg)

```
[![Health](https://phpackages.com/badges/tanthammar-laravel-extras/health.svg)](https://phpackages.com/packages/tanthammar-laravel-extras)
```

###  Alternatives

[resultsystems/validation

Inspired 'KennedyTedesco Validation' - The power of 'Respect Validation' on Laravel.

2832.4k4](/packages/resultsystems-validation)[carsdotcom/laravel-json-schema

Json Schema validation for Laravel projects

1036.7k3](/packages/carsdotcom-laravel-json-schema)[iutrace/laravel-cuit-validator

Argentinian CUIT and CUIL Validator

1013.3k](/packages/iutrace-laravel-cuit-validator)

PHPackages © 2026

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