PHPackages                             uzbek/laravel-partition-manager - 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. [Database &amp; ORM](/categories/database)
4. /
5. uzbek/laravel-partition-manager

ActiveLibrary[Database &amp; ORM](/categories/database)

uzbek/laravel-partition-manager
===============================

A Laravel package for managing PostgreSQL partitioned tables

v0.3.4(4mo ago)034MITPHPPHP ^8.3

Since Dec 5Pushed 4mo agoCompare

[ Source](https://github.com/professor93/laravel-partition-manager)[ Packagist](https://packagist.org/packages/uzbek/laravel-partition-manager)[ RSS](/packages/uzbek-laravel-partition-manager/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (3)Versions (13)Used By (0)

Laravel Partition Manager
=========================

[](#laravel-partition-manager)

A powerful Laravel package for managing PostgreSQL partitioned tables. Supports RANGE, LIST, and HASH partitioning strategies with multi-level sub-partitioning, automatic partition generation, and schema management.

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

[](#requirements)

- PHP 8.3 or higher
- Laravel 12.0 or higher
- PostgreSQL 14 or higher

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

[](#table-of-contents)

- [Installation](#installation)
- [Quick Start](#quick-start)
- [Features](#features)
- [Partition Types](#partition-types)
    - [Range Partitioning](#range-partitioning)
    - [List Partitioning](#list-partitioning)
    - [Hash Partitioning](#hash-partitioning)
- [Automatic Partition Generation](#automatic-partition-generation)
    - [Terminal Methods](#terminal-methods)
    - [Quick Generation for Existing Tables](#quick-generation-for-existing-tables)
    - [DateRangeBuilder](#daterangebuilder)
- [Schema Management](#schema-management)
- [Sub-Partitioning](#sub-partitioning)
- [Partition Management](#partition-management)
- [Artisan Commands](#artisan-commands)
- [Scheduler Integration](#scheduler-integration)
- [Partition Templates](#partition-templates)
- [Model Trait](#model-trait)
- [Advanced Features](#advanced-features)
- [Configuration](#configuration)
- [Service Classes](#service-classes)
- [API Reference](#api-reference)
- [License](#license)

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

[](#installation)

Install the package via Composer:

```
composer require uzbek/laravel-partition-manager
```

Optionally publish the configuration:

```
php artisan vendor:publish --tag=partition-manager-config
```

Quick Start
-----------

[](#quick-start)

```
use Uzbek\LaravelPartitionManager\Partition;

// Create a partitioned table with 12 monthly partitions
Partition::create('logs', function($table) {
    $table->id();
    $table->string('level');
    $table->text('message');
    $table->timestamp('created_at');
})
->by('created_at')
->monthly();

// Add partitions to an existing table
Partition::for('events')
    ->by('created_at')
    ->daily(30);
```

Features
--------

[](#features)

- **Three Partitioning Strategies**: RANGE, LIST, and HASH partitioning
- **Automatic Partition Generation**: Monthly, yearly, daily, weekly, quarterly partitions
- **Multi-Level Sub-Partitioning**: Create hierarchical partition structures
- **Schema Management**: Per-partition schema assignment with auto-creation
- **Transaction Safety**: All operations wrapped in transactions with automatic rollback
- **Partition Lifecycle Management**: Attach, detach, drop, analyze, vacuum operations
- **Advanced Options**: Default partitions, check constraints, custom tablespaces, partition pruning
- **Multi-Column Partitioning**: Partition by multiple columns or custom expressions
- **Artisan Commands**: 8 CLI commands for partition management and maintenance
- **Scheduler Integration**: Schedule partition rotation and creation via Laravel's scheduler
- **Partition Templates**: Reusable partition configurations with placeholder support
- **Model Trait**: Partition-aware Eloquent queries with scopes and helper methods
- **Laravel Octane Support**: Proper cache management for long-running processes

Partition Types
---------------

[](#partition-types)

### Range Partitioning

[](#range-partitioning)

Divide data based on ranges of values, ideal for date-based partitioning.

```
// Simple syntax with terminal method
Partition::create('orders', function($table) {
    $table->id();
    $table->decimal('amount');
    $table->date('order_date');
})
->by('order_date')
->monthly(24, '2024-01-01');  // 24 partitions from Jan 2024

// Manual partition definition
Partition::create('orders', function($table) {
    $table->id();
    $table->decimal('amount');
    $table->date('order_date');
})
->by('order_date')
->addRangePartition('orders_2024_q1', '2024-01-01', '2024-04-01')
->addRangePartition('orders_2024_q2', '2024-04-01', '2024-07-01')
->generate();  // Required when using addRangePartition()
```

### List Partitioning

[](#list-partitioning)

Partition data based on discrete values.

```
Partition::create('users', function($table) {
    $table->id();
    $table->string('country');
    $table->string('email');
})
->by('country')
->addListPartition('users_us', ['US', 'CA'])
->addListPartition('users_eu', ['DE', 'FR', 'IT', 'ES'])
->addListPartition('users_asia', ['JP', 'CN', 'KR'])
->generate();

// Or use addListPartitions for bulk creation
Partition::create('orders', function($table) {
    $table->id();
    $table->string('status');
})
->by('status')
->addListPartitions(['pending', 'processing', 'shipped', 'delivered'])
->generate();
```

### Hash Partitioning

[](#hash-partitioning)

Distribute data evenly across partitions using a hash function.

```
Partition::create('events', function($table) {
    $table->id();
    $table->string('event_type');
    $table->jsonb('payload');
})
->by('id')
->addHashPartitions(4)
->generate();
```

Automatic Partition Generation
------------------------------

[](#automatic-partition-generation)

### Terminal Methods

[](#terminal-methods)

Terminal methods create the table and partitions immediately (no `generate()` call needed):

```
Partition::create('logs', function($table) { /* ... */ })
->by('created_at')
->monthly();           // 12 monthly partitions from current month
->monthly(24);         // 24 monthly partitions
->monthly(12, '2024-01-01');  // From specific date

->yearly();            // 5 yearly partitions from current year
->yearly(10, 2020);    // 10 partitions starting from 2020

->daily();             // 30 daily partitions from today
->daily(7, '2024-01-01');

->weekly();            // 12 weekly partitions
->quarterly();         // 8 quarterly partitions
```

#### Flexible Date Input

[](#flexible-date-input)

All date parameters accept multiple formats:

```
// Integer year
->monthly(12, 2024);           // Starts from 2024-01-01
->yearly(5, 2024);             // Starts from 2024-01-01

// Partial date strings
->monthly(12, '2024');         // Starts from 2024-01-01
->monthly(12, '2024-06');      // Starts from 2024-06-01

// Full date strings
->monthly(12, '2024-06-15');   // Starts from 2024-06-01 (aligned to month)

// DateTime/Carbon objects
->monthly(12, new DateTime('2024-06-15'));
->monthly(12, Carbon::now()->subMonth());

// Start from today explicitly
->monthly(12, fromToday: true);
```

### Quick Generation for Existing Tables

[](#quick-generation-for-existing-tables)

```
// One-liner methods
Partition::monthly('logs', 'created_at', 12);
Partition::yearly('reports', 'year', 5);
Partition::daily('metrics', 'recorded_at', 30);
Partition::weekly('events', 'event_date', 12);
Partition::quarterly('sales', 'sale_date', 8);

// Using the builder for more control
Partition::for('logs')
    ->by('created_at')
    ->schema('log_partitions')
    ->monthly(24);

// List partitions
Partition::for('regions')
    ->byList('country', [
        'us' => ['US', 'CA'],
        'eu' => ['DE', 'FR', 'ES'],
        'asia' => ['JP', 'CN', 'KR']
    ]);

// Hash partitions
Partition::for('users')
    ->byHash('id', 8);
```

### DateRangeBuilder

[](#daterangebuilder)

For advanced date range configurations:

```
use Uzbek\LaravelPartitionManager\Builders\DateRangeBuilder;

Partition::create('metrics', function($table) {
    $table->id();
    $table->float('value');
    $table->timestamp('recorded_at');
})
->by('recorded_at')
->dateRange(
    DateRangeBuilder::daily()
        ->from('2024-01-01')
        ->count(30)
        ->defaultSchema('daily_metrics')
)
->generate();
```

Schema Management
-----------------

[](#schema-management)

### Per-Partition Schemas

[](#per-partition-schemas)

```
// Default schema for all partitions
Partition::create('logs', function($table) { /* ... */ })
->by('logged_at')
->schema('log_partitions')
->monthly();

// Different schemas per partition
Partition::create('logs', function($table) { /* ... */ })
->by('logged_at')
->addRangePartition('logs_archive', '2023-01-01', '2024-01-01', 'archive_schema')
->addRangePartition('logs_current', '2024-01-01', '2025-01-01', 'current_schema')
->generate();
```

### SchemaCreator Service

[](#schemacreator-service)

```
use Uzbek\LaravelPartitionManager\Services\SchemaCreator;

// Ensure schema exists
SchemaCreator::ensure('my_schema');
SchemaCreator::ensure('my_schema', $connection);

// Ensure schema and return prefixed table name
$fullName = SchemaCreator::ensureAndPrefix('my_table', 'my_schema');
// Returns: 'my_schema.my_table'
```

### PartitionSchemaManager Service

[](#partitionschemamanager-service)

```
use Uzbek\LaravelPartitionManager\Services\PartitionSchemaManager;

$schemaManager = new PartitionSchemaManager();

$schemaManager->setDefault('default_partitions');
$schemaManager->register('error', 'error_log_schema');
$schemaManager->registerMultiple([
    'active' => 'active_schema',
    'archived' => 'archive_schema'
]);

$schema = $schemaManager->getSchemaFor('error');
$hasSchema = $schemaManager->hasSchemaFor('info');
```

Sub-Partitioning
----------------

[](#sub-partitioning)

Create hierarchical partition structures with support for unlimited nesting levels.

### Inline Sub-Partitions (Recommended)

[](#inline-sub-partitions-recommended)

The cleanest way to define sub-partitions - no need to repeat partition names:

```
use Uzbek\LaravelPartitionManager\Builders\SubPartitionBuilder;

Partition::create('events', function($table) {
    $table->id();
    $table->string('type');
    $table->integer('user_id');
    $table->timestamp('created_at');
})
->by('created_at')
->addRangePartition('events_2024_01', '2024-01-01', '2024-02-01',
    subPartitions: SubPartitionBuilder::list('type')
        ->addListPartition('events_2024_01_user', ['login', 'logout'])
        ->addListPartition('events_2024_01_system', ['error', 'warning'])
)
->generate();
```

### Separate Declaration

[](#separate-declaration)

You can also declare sub-partitions separately using `withSubPartitions()`:

```
Partition::create('events', function($table) { /* ... */ })
->by('created_at')
->addRangePartition('events_2024_01', '2024-01-01', '2024-02-01')
->withSubPartitions('events_2024_01',
    SubPartitionBuilder::list('type')
        ->addListPartition('events_2024_01_user', ['login', 'logout'])
        ->addListPartition('events_2024_01_system', ['error', 'warning'])
)
->generate();
```

### Apply Same Sub-Partition to All Partitions

[](#apply-same-sub-partition-to-all-partitions)

Use `addSubPartitionToAll()` to apply the same sub-partition configuration to all existing partitions:

```
Partition::create('logs', function($table) {
    $table->id();
    $table->integer('user_id');
    $table->timestamp('created_at');
})
->by('created_at')
->addMonthlyPartitions(12, '2024-01-01')
->addSubPartitionToAll(
    SubPartitionBuilder::hash('user_id')
        ->addHashPartitions(4, '%_shard_')  // % = partition name
        // Creates: logs_m2024_01_shard_0, logs_m2024_01_shard_1, etc.
)
->generate();
```

The `%` placeholder in prefixes is replaced with the parent partition name, making it easy to create hierarchical naming.

### Multi-Level Nesting

[](#multi-level-nesting)

Sub-partitions can have their own sub-partitions, enabling complex hierarchical structures:

```
// Example: LIST → HASH → RANGE (3 levels deep)
Partition::create('orders', function($table) {
    $table->id();
    $table->string('status');
    $table->integer('user_id');
    $table->timestamp('created_at');
})
->list()
->by('status')
->addListPartition('orders_active', ['pending', 'processing'],
    subPartitions: SubPartitionBuilder::hash('user_id')
        ->addHashPartition('active_shard_0', 4, 0,
            subPartitions: SubPartitionBuilder::range('created_at')
                ->addMonthlyPartitions('m_', 12)
        )
        ->addHashPartition('active_shard_1', 4, 1,
            subPartitions: SubPartitionBuilder::range('created_at')
                ->addMonthlyPartitions('m_', 12)
        )
        ->addHashPartition('active_shard_2', 4, 2)
        ->addHashPartition('active_shard_3', 4, 3)
)
->addListPartition('orders_completed', ['shipped', 'delivered'])
->generate();
```

### Using Value Objects

[](#using-value-objects)

```
use Uzbek\LaravelPartitionManager\ValueObjects\RangePartition;
use Uzbek\LaravelPartitionManager\ValueObjects\ListSubPartition;

$partition = RangePartition::range('data_2024_01')
    ->withRange('2024-01-01', '2024-02-01')
    ->withSchema('monthly_data')
    ->withSubPartitions(
        SubPartitionBuilder::list('status')
            ->add(ListSubPartition::create('data_active')
                ->withValues(['active', 'pending'])
                ->withSchema('active_data'))
    );

$builder->addPartition($partition);
```

### Add Sub-Partitions to Existing Partitions

[](#add-sub-partitions-to-existing-partitions)

Convert an existing non-partitioned partition into a partitioned one:

```
use Uzbek\LaravelPartitionManager\Services\PartitionMaintenance;

// Add sub-partitions to an existing partition (auto-detects partition expression)
PartitionMaintenance::addSubPartitions(
    'orders',                    // parent table
    'orders_active',             // existing partition to sub-partition
    SubPartitionBuilder::hash('user_id')->addHashPartitions('shard_', 8)
);

// Or manually specify the partition expression
PartitionMaintenance::addSubPartitions(
    'orders',
    'orders_active',
    SubPartitionBuilder::hash('user_id')->addHashPartitions('shard_', 8),
    "FOR VALUES IN ('active', 'pending')"  // optional, auto-detected if omitted
);
```

Partition Management
--------------------

[](#partition-management)

### Runtime Operations

[](#runtime-operations)

```
use Uzbek\LaravelPartitionManager\Services\PartitionManager;

$manager = app(PartitionManager::class);

// List all partitions
$partitions = $manager->getPartitions('logs');

// Get partition details
$info = $manager->getPartitionInfo('logs', 'logs_2024_01');

// Get partition strategy
$strategy = $manager->getPartitionStrategy('logs');
// Returns: PartitionType::RANGE, LIST, or HASH

// Check if table is partitioned
if ($manager->isPartitioned('logs')) { /* ... */ }

// Get statistics
$size = $manager->getTableSize('logs');
$count = $manager->getPartitionCount('logs');
$oldest = $manager->getOldestPartition('logs');
$newest = $manager->getNewestPartition('logs');

// Drop old partitions
$dropped = $manager->dropOldPartitions('logs', new DateTime('-6 months'));

// Maintenance
$manager->analyzePartition('logs_2024_01');
$manager->vacuumPartition('logs_2024_01', full: true);
```

### Table Operations

[](#table-operations)

```
use Uzbek\LaravelPartitionManager\Builders\PostgresPartitionBuilder;

$builder = new PostgresPartitionBuilder('orders');

// Attach existing table as partition
$builder->attachPartition('old_orders', 'orders_2023', '2023-01-01', '2024-01-01');

// Detach partition (optionally with CONCURRENTLY)
$builder->detachPartition('orders_2023', concurrently: true);

// Drop partition
$builder->dropPartition('orders_2023');

// Maintenance
$builder->analyze();
$builder->vacuum();
$builder->vacuum(full: true);
```

### Using Facades

[](#using-facades)

```
use Uzbek\LaravelPartitionManager\Facades\PartitionManager;

$partitions = PartitionManager::getPartitions('logs');
$isPartitioned = PartitionManager::isPartitioned('logs');
$strategy = PartitionManager::getPartitionStrategy('logs');
```

Artisan Commands
----------------

[](#artisan-commands)

The package provides 8 Artisan commands for managing partitions from the command line:

### partition:list

[](#partitionlist)

List all partitions for a table with size and row count:

```
php artisan partition:list orders

# Output:
# +------------------+------------+----------+
# | Partition        | Rows       | Size     |
# +------------------+------------+----------+
# | orders_m2024_01  | 15,234     | 2.1 MB   |
# | orders_m2024_02  | 18,456     | 2.5 MB   |
# | orders_m2024_03  | 12,890     | 1.8 MB   |
# +------------------+------------+----------+
```

### partition:tree

[](#partitiontree)

Display partition hierarchy as a tree:

```
php artisan partition:tree orders --depth=2

# Output:
# orders (partitioned by RANGE)
# ├── orders_2024_01 [2024-01-01 → 2024-02-01]
# ├── orders_2024_02 [2024-02-01 → 2024-03-01]
# └── orders_2024_03 [2024-03-01 → 2024-04-01]
```

### partition:health

[](#partitionhealth)

Run a health check on partitions:

```
php artisan partition:health orders

# Checks for:
# - Gaps between partitions
# - Overlapping ranges
# - Missing indexes
# - Orphan data in default partition
```

### partition:ensure-future

[](#partitionensure-future)

Create future partitions proactively:

```
# Ensure 3 monthly partitions exist
php artisan partition:ensure-future orders created_at --count=3 --interval=monthly

# With custom schema
php artisan partition:ensure-future orders created_at --count=6 --interval=monthly --schema=archive
```

### partition:drop-old

[](#partitiondrop-old)

Drop partitions older than a threshold:

```
# Drop partitions older than 6 months
php artisan partition:drop-old logs --keep=6

# Preview without dropping
php artisan partition:drop-old logs --keep=6 --dry-run
```

### partition:vacuum

[](#partitionvacuum)

Run VACUUM on partitions:

```
# Vacuum specific partition
php artisan partition:vacuum orders_2024_01

# Vacuum all partitions of a table
php artisan partition:vacuum orders --all

# Full vacuum (reclaims more space, locks table)
php artisan partition:vacuum orders_2024_01 --full

# Vacuum with analyze
php artisan partition:vacuum orders_2024_01 --analyze
```

### partition:reindex

[](#partitionreindex)

Rebuild indexes on partitions:

```
# Reindex specific partition
php artisan partition:reindex orders_2024_01

# Reindex concurrently (non-blocking)
php artisan partition:reindex orders_2024_01 --concurrently

# Reindex all partitions
php artisan partition:reindex orders --all
```

### partition:analyze

[](#partitionanalyze)

Update statistics for query planner:

```
# Analyze specific partition
php artisan partition:analyze orders_2024_01

# Analyze all partitions
php artisan partition:analyze orders --all
```

Scheduler Integration
---------------------

[](#scheduler-integration)

Schedule partition maintenance tasks using Laravel's scheduler with a fluent API:

### Basic Usage

[](#basic-usage)

In your `app/Console/Kernel.php` or `routes/console.php`:

```
use Illuminate\Console\Scheduling\Schedule;

$schedule->partition('orders', 'created_at')
    ->ensureFuture(3, 'monthly')
    ->daily();

$schedule->partition('logs', 'created_at')
    ->rotate(keep: 12)
    ->monthly();
```

### Combined Operations

[](#combined-operations)

Run both creation and rotation in a single scheduled task:

```
$schedule->partition('events', 'created_at')
    ->ensureFuture(3, 'monthly')
    ->rotate(keep: 24)
    ->schema('event_partitions')
    ->dailyAt('02:00')
    ->withoutOverlapping()
    ->onOneServer();
```

### Available Methods

[](#available-methods)

```
$schedule->partition(string $table, string $column)
    // Partition operations
    ->ensureFuture(int $count, string $interval = 'monthly')  // Create future partitions
    ->rotate(int $keep, bool $dropSchemas = false)            // Drop old partitions
    ->schema(string $schema)                                   // Schema for new partitions

    // Scheduling options (all Laravel scheduler methods available)
    ->daily()
    ->dailyAt('02:00')
    ->weekly()
    ->weeklyOn(1, '03:00')  // Monday at 3 AM
    ->monthly()
    ->monthlyOn(1, '04:00')
    ->cron('0 2 * * *')
    ->timezone('America/New_York')

    // Constraints
    ->withoutOverlapping()
    ->onOneServer()
    ->evenInMaintenanceMode()
    ->runInBackground()

    // Callbacks
    ->onSuccess(fn($result) => Log::info($result->summary()))
    ->onFailure(fn($e) => Log::error($e->getMessage()))
    ->name('partition-maintenance:orders');
```

### Result Object

[](#result-object)

The scheduled task returns a `PartitionScheduleResult` object:

```
$schedule->partition('orders', 'created_at')
    ->ensureFuture(3, 'monthly')
    ->rotate(keep: 12)
    ->daily()
    ->onSuccess(function (PartitionScheduleResult $result) {
        if ($result->hasChanges()) {
            Log::info($result->summary());
            // Output: "Partition maintenance: created 2 partition(s), dropped 1 partition(s)"
        }

        echo $result->partitionsCreated;      // Number created
        echo count($result->partitionsDropped); // Names of dropped partitions
    });
```

Partition Templates
-------------------

[](#partition-templates)

Templates provide reusable partition configurations that can be applied to multiple tables. The `%` placeholder is replaced with the table name.

### Configuration

[](#configuration)

Define templates in `config/partition-manager.php`:

```
'templates' => [
    'monthly_archive' => [
        'type' => 'range',
        'column' => 'created_at',
        'interval' => 'monthly',
        'count' => 12,
        'schema' => '%_archive',        // orders → orders_archive
        'default_partition' => true,
        'future_partitions' => 3,
    ],

    'tenant_hash' => [
        'type' => 'hash',
        'column' => 'tenant_id',
        'modulus' => 16,
        'schema' => 'tenants',
    ],

    'status_list' => [
        'type' => 'list',
        'column' => 'status',
        'values' => ['pending', 'active', 'completed', 'cancelled'],
        'default_partition' => true,
    ],
],
```

### Using Templates in Migrations

[](#using-templates-in-migrations)

```
use Uzbek\LaravelPartitionManager\Partition;

// Apply template from config
Partition::create('orders', function($table) {
    $table->id();
    $table->decimal('amount');
    $table->timestamp('created_at');
})
->fromTemplate('monthly_archive')
->generate();

// Override template settings
Partition::create('events', function($table) {
    $table->id();
    $table->timestamp('created_at');
})
->fromTemplate('monthly_archive', [
    'count' => 24,
    'schema' => 'event_archive',
])
->generate();
```

### Programmatic Templates

[](#programmatic-templates)

Create templates programmatically:

```
use Uzbek\LaravelPartitionManager\Templates\PartitionTemplate;

$template = PartitionTemplate::define('custom')
    ->range('created_at')
    ->monthly(12)
    ->withSchema('%_partitions')
    ->withDefaultPartition()
    ->withFuturePartitions(3);

Partition::create('logs', fn($t) => $t->id()->timestamps())
    ->fromTemplate($template)
    ->generate();
```

### Template Methods

[](#template-methods)

```
PartitionTemplate::define(string $name)
    // Partition type
    ->range(string|array $columns)
    ->list(string $column)
    ->hash(string $column, int $modulus)

    // Intervals (for RANGE)
    ->daily(int $count = 30)
    ->weekly(int $count = 12)
    ->monthly(int $count = 12)
    ->yearly(int $count = 5)

    // LIST values
    ->withValues(array $values)

    // Options
    ->withSchema(string $schema)           // Supports % placeholder
    ->withTablespace(string $tablespace)
    ->withPrefix(string $prefix)           // Supports % placeholder
    ->withDefaultPartition(bool $enabled = true)
    ->withFuturePartitions(int $count);
```

Model Trait
-----------

[](#model-trait)

The `HasPartitions` trait adds partition-aware methods to your Eloquent models:

### Basic Setup

[](#basic-setup)

```
use Illuminate\Database\Eloquent\Model;
use Uzbek\LaravelPartitionManager\Traits\HasPartitions;

class Order extends Model
{
    use HasPartitions;

    // Optional: specify the partition column (default: 'created_at')
    protected static string $partitionColumn = 'created_at';
}
```

### Query Scopes

[](#query-scopes)

Query specific partitions directly:

```
// Query a specific partition by name
Order::inPartition('orders_m2024_01')->where('status', 'pending')->get();

// Query by date range (enables partition pruning)
Order::inPartitionRange('2024-01-01', '2024-03-31')->get();

// Query by value (for LIST partitions)
Order::inPartitionValue('active')->get();
Order::inPartitionValues(['pending', 'processing'])->get();
```

### Partition Information

[](#partition-information)

```
// Check if table is partitioned
if (Order::isPartitioned()) {
    // Get all partitions
    $partitions = Order::getPartitions();

    // Get partition strategy (RANGE, LIST, HASH)
    $strategy = Order::getPartitionStrategy();

    // Get statistics
    $stats = Order::getPartitionStats();

    // Get boundaries
    $boundaries = Order::getPartitionBoundaries();
}
```

### Finding Partitions

[](#finding-partitions)

```
// Find partition for a specific date (RANGE)
$partitionName = Order::getPartitionForDate('2024-06-15');
// Returns: 'orders_m2024_06' or null

// Check if partition exists for date
if (Order::hasPartitionForDate('2024-12-01')) {
    // Safe to insert
}

// Find partition for a value (LIST)
$partitionName = Order::getPartitionForValue('active');
```

### Health and Statistics

[](#health-and-statistics)

```
// Run health check
$health = Order::partitionHealthCheck();
// Returns: ['gaps' => [...], 'overlaps' => [...], 'missing_indexes' => [...], 'orphan_data' => bool]

// Estimate total rows
$totalRows = Order::estimateTotalRows();

// Count rows in specific partition
$count = Order::countInPartition('orders_m2024_01');

// Get oldest/newest partition
$oldest = Order::getOldestPartition();
$newest = Order::getNewestPartition();
```

### Query Analysis

[](#query-analysis)

```
// Explain partition pruning for a query
$query = Order::where('created_at', '>=', '2024-01-01')
    ->where('created_at', 'conditionalIndex(['code'], "status = 'void'");
    // Creates: promo_codes_code_idx

    // With custom name
    $table->conditionalIndex(['code'], "status = 'void'", 'idx_pc_void');

    // Laravel-style closure for WHERE clause
    $table->conditionalIndex(['source_type', 'source_id'], function ($query) {
        $query->whereIn('status', ['new', 'dispensed'])
              ->whereNotNull('source_type');
    }, 'idx_pc_source');
});

Schema::table('user_daily_points', function (Blueprint $table) {
    // Index with column ordering (no WHERE clause)
    $table->conditionalIndex(['date', 'points' => 'DESC']);

    // Alternative syntax: ordering in column string
    $table->conditionalIndex(['date ASC', 'points DESC'], name: 'idx_udp_sorted');

    // With closure and ordering
    $table->conditionalIndex(
        ['created_at' => 'DESC', 'score' => 'DESC'],
        fn($q) => $q->where('status', 'active'),
        'idx_active_users'
    );

    // Custom index method (e.g., GIN for JSONB columns)
    $table->conditionalIndex(['metadata'], method: 'gin');
});
```

Parameters:

- `$columns`: Array of columns with optional ordering
    - String value: column name (e.g., `'code'` or `'points DESC'`)
    - Key-value: `'column' => 'ASC'` or `'column' => 'DESC'`
- `$where`: Optional WHERE clause - raw string or Laravel-style closure
- `$name`: Optional index name (auto-generated as `{table}_{columns}_idx` if null)
- `$method`: Index method - `btree` (default), `hash`, `gist`, `gin`, `brin`

### Default Partitions

[](#default-partitions)

Catch rows that don't match any defined partition:

```
->withDefaultPartition('others')
```

### Check Constraints

[](#check-constraints)

```
->check('positive_amount', 'amount > 0')
->check('valid_status', "status IN ('pending', 'completed')")
```

### Partition Pruning

[](#partition-pruning)

```
->enablePartitionPruning()      // Enable query optimization
->detachConcurrently()          // Non-blocking detach operations
```

### Custom Tablespaces

[](#custom-tablespaces)

```
->tablespace('fast_ssd')
```

### Custom Partition Expressions

[](#custom-partition-expressions)

```
->partitionByExpression("DATE_TRUNC('week', event_time AT TIME ZONE timezone)")
->partitionByYear('order_date')
->partitionByMonth('created_at')
->partitionByDay('logged_at')
```

### Multi-Column Partitioning

[](#multi-column-partitioning)

```
Partition::create('sales', function($table) {
    $table->id();
    $table->string('region');
    $table->integer('year');
    $table->decimal('amount');
})
->by(['region', 'year'])
->addRangePartition('sales_us_2024', ['US', 2024], ['US', 2025])
->generate();
```

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

[](#configuration-1)

```
// config/partition-manager.php
return [
    'default_connection' => env('DB_CONNECTION', 'pgsql'),

    'defaults' => [
        'enable_partition_pruning' => true,
        'detach_concurrently' => true,
        'analyze_after_create' => true,
        'vacuum_after_drop' => true,
    ],

    'naming' => [
        'prefix' => '',
        'suffix' => '',
        'separator' => '_',
        'date_format' => 'Y_m',
        'day_format' => 'Y_m_d',
    ],

    'schemas' => [
        'auto_create' => [],
        'default' => null,
        'mappings' => [],
    ],

    'logging' => [
        'enabled' => env('PARTITION_LOGGING', true),
        'channel' => env('PARTITION_LOG_CHANNEL', 'daily'),
    ],
];
```

Service Classes
---------------

[](#service-classes)

The package provides standalone service classes for specific partition operations:

### PartitionStats

[](#partitionstats)

Get statistics and health information about partitions:

```
use Uzbek\LaravelPartitionManager\Services\PartitionStats;

// Get partition statistics (row count, size)
$stats = PartitionStats::get('orders');
// Returns: partition_name, row_count, size_bytes, size_pretty

// Get partition boundaries
$boundaries = PartitionStats::boundaries('orders');
// Returns: partition_name, partition_type, from_value, to_value

// Estimate row counts
$rowCount = PartitionStats::estimateRowCount('orders');
$totalRows = PartitionStats::estimateTotalRowCount('orders');

// Health check
$health = PartitionStats::healthCheck('orders');
// Returns: gaps, overlaps, missing_indexes, orphan_data

// Find specific issues
$gaps = PartitionStats::findGaps('orders');
$overlaps = PartitionStats::findOverlaps('orders');
$missingIndexes = PartitionStats::findMissingIndexes('orders');

// Analyze query pruning
$pruning = PartitionStats::explainPruning(
    "SELECT * FROM orders WHERE created_at >= '2024-01-01'"
);
// Returns: partitions_scanned, total_partitions, pruning_effective, plan

// Tree visualization
$tree = PartitionStats::getTree('orders');
echo PartitionStats::printTree('orders');
// Output:
// orders
// ├── orders_2024_01 [2024-01-01 → 2024-02-01]
// ├── orders_2024_02 [2024-02-01 → 2024-03-01]
// └── orders_2024_03 [2024-03-01 → 2024-04-01]
```

### PartitionMaintenance

[](#partitionmaintenance)

Perform maintenance operations on partitions:

```
use Uzbek\LaravelPartitionManager\Services\PartitionMaintenance;
use Uzbek\LaravelPartitionManager\Builders\SubPartitionBuilder;

// Vacuum partition (reclaim storage)
PartitionMaintenance::vacuum('orders_2024_01');
PartitionMaintenance::vacuum('orders_2024_01', full: true);
PartitionMaintenance::vacuum('orders_2024_01', analyze: true);

// Vacuum all partitions of a table
PartitionMaintenance::vacuumAll('orders');
PartitionMaintenance::vacuumAll('orders', full: true);

// Analyze partition (update statistics)
PartitionMaintenance::analyze('orders_2024_01');
PartitionMaintenance::analyzeAll('orders');

// Reindex partition
PartitionMaintenance::reindex('orders_2024_01');
PartitionMaintenance::reindex('orders_2024_01', concurrently: true);
PartitionMaintenance::reindexAll('orders');

// Rebalance hash partitions (change modulus)
PartitionMaintenance::rebalanceHash('events', newModulus: 16);
PartitionMaintenance::rebalanceHash('events', newModulus: 16, schema: 'partitions');

// Add sub-partitions to an existing partition
PartitionMaintenance::addSubPartitions(
    'orders',
    'orders_active',
    SubPartitionBuilder::hash('user_id')->addHashPartitions('shard_', 8)
);

// Get partition expression for an existing partition
$expr = PartitionMaintenance::getPartitionExpression('orders', 'orders_active');
// Returns: "FOR VALUES IN ('active', 'pending')"

// Get commands for parallel execution via jobs/CLI
$commands = PartitionMaintenance::getParallelVacuumCommands('orders');
$commands = PartitionMaintenance::getParallelReindexCommands('orders', concurrently: true);
$commands = PartitionMaintenance::getParallelAnalyzeCommands('orders');

// Dry run mode - returns SQL without executing
$queries = PartitionMaintenance::dryRun(function() {
    PartitionMaintenance::vacuum('orders_2024_01');
    PartitionMaintenance::analyze('orders_2024_01');
});
```

### PartitionConsolidator

[](#partitionconsolidator)

Merge multiple partitions into larger ones:

```
use Uzbek\LaravelPartitionManager\Services\PartitionConsolidator;

// Merge specific partitions
PartitionConsolidator::merge(
    'orders',
    ['orders_2024_01', 'orders_2024_02', 'orders_2024_03'],
    'orders_2024_q1',
    '2024-01-01',
    '2024-04-01'
);

// Consolidate monthly partitions into yearly
PartitionConsolidator::monthlyToYearly('orders', 2024, 'orders_m');

// Consolidate daily partitions into weekly
PartitionConsolidator::dailyToWeekly('logs', '2024-01-01', 'logs_d');

// Consolidate daily partitions into monthly
PartitionConsolidator::dailyToMonthly('logs', 2024, 1, 'logs_d');

// Consolidate weekly partitions into monthly
PartitionConsolidator::weeklyToMonthly('events', 2024, 1, 'events_w');

// Merge all partitions within a date range
PartitionConsolidator::range(
    'orders',
    '2024-01-01',
    '2024-07-01',
    'orders_2024_h1'
);
```

### PartitionSplitter

[](#partitionsplitter)

Split partitions into smaller granularity:

```
use Uzbek\LaravelPartitionManager\Services\PartitionSplitter;

// Split yearly partition into monthly
PartitionSplitter::yearlyToMonthly('orders', 'orders_y2024', 2024);

// Split yearly partition into weekly
PartitionSplitter::yearlyToWeekly('events', 'events_y2024', 2024);

// Split monthly partition into daily
PartitionSplitter::monthlyToDaily('logs', 'logs_m2024_01', 2024, 1);

// Split monthly partition into weekly
PartitionSplitter::monthlyToWeekly('events', 'events_m2024_01', 2024, 1);

// Custom split with specific ranges
PartitionSplitter::custom('orders', 'orders_q1', [
    'orders_jan' => ['from' => '2024-01-01', 'to' => '2024-02-01'],
    'orders_feb' => ['from' => '2024-02-01', 'to' => '2024-03-01'],
    'orders_mar' => ['from' => '2024-03-01', 'to' => '2024-04-01'],
]);
```

### PartitionRotation

[](#partitionrotation)

Manage partition lifecycle with rotation policies:

```
use Uzbek\LaravelPartitionManager\Services\PartitionRotation;

// Ensure future partitions exist (column and interval are auto-detected if omitted)
$created = PartitionRotation::ensureFuture('orders', count: 3);
$created = PartitionRotation::ensureFuture('orders', 3, 'created_at', 'monthly');

// Rotate old partitions (keep only the most recent N partitions)
$dropped = PartitionRotation::rotate('logs', keep: 12);

// Add monthly partitions for an entire year
// Year accepts: int, string ("2025"), or DateTimeInterface
PartitionRotation::addMonthlyForYear('orders', 'created_at', 2025);
PartitionRotation::addMonthlyForYear('orders', 'created_at', '2025');
```

### PartitionIndex

[](#partitionindex)

Manage indexes on partitions:

```
use Uzbek\LaravelPartitionManager\Services\PartitionIndex;

// Create index on partition
PartitionIndex::create('orders_2024_01', 'idx_orders_customer', ['customer_id']);

// Create unique index
PartitionIndex::create('orders_2024_01', 'idx_orders_ref', ['reference'], unique: true);

// Create index with specific method (btree, hash, gist, gin, brin)
PartitionIndex::create('logs_2024_01', 'idx_logs_message', ['message'], method: 'gin');

// Create index concurrently (non-blocking)
PartitionIndex::createConcurrently('orders_2024_01', 'idx_customer', ['customer_id']);

// Drop index
PartitionIndex::drop('idx_orders_customer');
PartitionIndex::drop('idx_orders_customer', cascade: true);
PartitionIndex::dropConcurrently('idx_orders_customer');

// List indexes on partition
$indexes = PartitionIndex::list('orders_2024_01');
```

### PartitionExport

[](#partitionexport)

Export partition data to files:

```
use Uzbek\LaravelPartitionManager\Services\PartitionExport;

// Export to SQL file
PartitionExport::toSql('orders_2024_01', '/backup/orders_2024_01.sql');

// Export to compressed SQL
PartitionExport::toCompressedSql('orders_2024_01', '/backup/orders_2024_01.sql.gz');

// Export to CSV
PartitionExport::toCsv('orders_2024_01', '/backup/orders_2024_01.csv');

// Get export command (without executing)
$command = PartitionExport::getExportCommand('orders_2024_01', '/backup/orders.sql');
```

API Reference
-------------

[](#api-reference)

### Partition (Static Helper)

[](#partition-static-helper)

```
Partition::create(string $table, Closure $callback): PostgresPartitionBuilder
Partition::for(string $table): QuickPartitionBuilder

// Quick generation
Partition::monthly(string $table, string $column, int $count = 12): void
Partition::yearly(string $table, string $column, int $count = 5): void
Partition::daily(string $table, string $column, int $count = 30): void
Partition::weekly(string $table, string $column, int $count = 12): void
Partition::quarterly(string $table, string $column, int $count = 8): void

// Queries
Partition::isPartitioned(string $table): bool
Partition::getPartitions(string $table): array
Partition::partitionExists(string $table, string $partitionName): bool
Partition::dropIfExists(string $table, bool $withSchema = false): void
Partition::dropSchemaIfEmpty(string $schema): void
Partition::dropSchemaIfExists(string $schema): void

// Attach partitions (for all partition types)
Partition::attachPartition(string $table, string $partitionName, mixed $from, mixed $to): void  // RANGE
Partition::attachListPartition(string $table, string $partitionName, array $values): void       // LIST
Partition::attachHashPartition(string $table, string $partitionName, int $modulus, int $remainder): void  // HASH

// Detach partition
Partition::detachPartition(string $table, string $partitionName, bool $concurrently = false): void
```

### PartitionType Enum

[](#partitiontype-enum)

```
use Uzbek\LaravelPartitionManager\Enums\PartitionType;

PartitionType::RANGE    // 'RANGE'
PartitionType::LIST     // 'LIST'
PartitionType::HASH     // 'HASH'

// Helper methods
$type->isRange(): bool
$type->isList(): bool
$type->isHash(): bool

// PostgreSQL strategy codes
PartitionType::PG_STRATEGY_RANGE  // 'r'
PartitionType::PG_STRATEGY_LIST   // 'l'
PartitionType::PG_STRATEGY_HASH   // 'h'

// Create from PostgreSQL strategy code
PartitionType::fromPgStrategy('r')  // Returns PartitionType::RANGE
```

### PostgresPartitionBuilder

[](#postgrespartitionbuilder)

```
// Configuration
->setBlueprint(Blueprint $blueprint): self
->connection(string $connection): self
->partition(PartitionType|string $type): self  // Optional: auto-detected from add*Partition calls
->range(): self   // Optional: auto-detected
->list(): self    // Optional: auto-detected
->hash(): self    // Optional: auto-detected
->by(string|array $columns): self
->partitionByExpression(string $expression): self

// Adding single partitions (all support optional subPartitions parameter)
->addPartition(PartitionDefinition $partition): self
->addRangePartition(string $name, mixed $from, mixed $to, ?string $schema = null, ?AbstractSubPartitionBuilder $subPartitions = null): self
->addListPartition(string $name, array $values, ?string $schema = null, ?AbstractSubPartitionBuilder $subPartitions = null): self
->addHashPartition(string $name, int $modulus, int $remainder, ?string $schema = null, ?AbstractSubPartitionBuilder $subPartitions = null): self

// Adding multiple partitions at once (non-terminal)
// All prefix parameters support % as placeholder for table name
// All date parameters accept: int (year), string ("2024", "2024-01", "2024-01-15"), or DateTimeInterface
->addListPartitions(array $values, ?string $schema = null): self
// Examples: ['new', 'void', 'used'] or [true => '%_active', false => '%_inactive']
->addHashPartitions(int $modulus, ?string $prefix = null, ?string $schema = null): self
// Example: addHashPartitions(4, '%_shard_') creates: orders_shard_0, orders_shard_1, etc.
->addMonthlyPartitions(int $count, int|string|DateTimeInterface|null $start = null, ?string $prefix = null, ?string $schema = null, bool $fromToday = false): self
->addYearlyPartitions(int $count, int|string|DateTimeInterface|null $start = null, ?string $prefix = null, ?string $schema = null, bool $fromToday = false): self
->addWeeklyPartitions(int $count, int|string|DateTimeInterface|null $start = null, ?string $prefix = null, ?string $schema = null, bool $fromToday = false): self
->addDailyPartitions(int $count, int|string|DateTimeInterface|null $start = null, ?string $prefix = null, ?string $schema = null, bool $fromToday = false): self
->dateRange(DateRangeBuilder $builder): self

// Terminal methods (execute immediately, includes generate())
// All accept: int (year), string ("2024", "2024-01", "2024-01-15"), or DateTimeInterface
->monthly(int $count = 12, int|string|DateTimeInterface|null $start = null, bool $fromToday = false): void
->yearly(int $count = 5, int|string|DateTimeInterface|null $start = null, bool $fromToday = false): void
->daily(int $count = 30, int|string|DateTimeInterface|null $start = null, bool $fromToday = false): void
->weekly(int $count = 12, int|string|DateTimeInterface|null $start = null, bool $fromToday = false): void
->quarterly(int $count = 8, int|string|DateTimeInterface|null $start = null, bool $fromToday = false): void

// Schema management
->schema(string $schema): self
->schemaFor(string $partitionType, string $schema): self
->schemasFor(array $schemas): self

// Sub-partitions
->withSubPartitions(string $partitionName, SubPartitionBuilder $builder): self
->addSubPartitionToAll(AbstractSubPartitionBuilder $builder): self  // Apply same sub-partition to all partitions

// Advanced options
->withDefaultPartition(string $name = 'default'): self
->tablespace(string $tablespace): self
->check(string $name, string $expression): self
->enablePartitionPruning(bool $enable = true): self
->detachConcurrently(bool $enable = true): self

// Execution
->generate(): void

// Runtime operations
->attachPartition(string $tableName, string $partitionName, mixed $from, mixed $to): self
->detachPartition(string $partitionName, ?bool $concurrently = null): self
->dropPartition(string $partitionName): self
->analyze(): self
->vacuum(bool $full = false): self
```

### QuickPartitionBuilder

[](#quickpartitionbuilder)

```
QuickPartitionBuilder::table(string $table): self

->by(string $column): self
->schema(string $schema): self
->connection(string $connection): self

// Range partitions
// All accept: int (year), string ("2024", "2024-01", "2024-01-15"), or DateTimeInterface
->monthly(int $count = 12, int|string|DateTimeInterface|null $start = null, bool $fromToday = false): void
->yearly(int $count = 5, int|string|DateTimeInterface|null $start = null, bool $fromToday = false): void
->daily(int $count = 30, int|string|DateTimeInterface|null $start = null, bool $fromToday = false): void
->weekly(int $count = 12, int|string|DateTimeInterface|null $start = null, bool $fromToday = false): void
->quarterly(int $count = 8, int|string|DateTimeInterface|null $start = null, bool $fromToday = false): void

// List and hash
->byList(string $column, array $partitions): void
->byHash(string $column, int $count = 4): void
```

### DateRangeBuilder

[](#daterangebuilder-1)

```
DateRangeBuilder::monthly(): self
DateRangeBuilder::yearly(): self
DateRangeBuilder::daily(): self
DateRangeBuilder::weekly(): self
DateRangeBuilder::quarterly(): self

// Date parameters accept: int (year), string ("2024", "2024-01", "2024-01-15"), or DateTimeInterface
->from(int|string|DateTimeInterface $date): self
->to(int|string|DateTimeInterface $date): self
->count(int $count): self
->interval(string $interval): self
->nameFormat(string $format): self
->schema(string $schema): self
->build(string $prefix = ''): array
```

### SubPartitionBuilder

[](#subpartitionbuilder)

```
SubPartitionBuilder::list(string $column): ListSubPartitionBuilder
SubPartitionBuilder::range(string $column): RangeSubPartitionBuilder
SubPartitionBuilder::hash(string $column): HashSubPartitionBuilder

// Common methods
->for(string $baseName): self  // Set base name for auto-generating partition names
->table(string $tableName): self  // Set table name for column type lookups (auto-set when used via PostgresPartitionBuilder)
->schema(string $schema): self
->add(SubPartition $partition): self
->getBaseName(): ?string
->getTableName(): ?string
->getPartitionType(): PartitionType
->getPartitionColumn(): string
->toArray(?string $defaultSchema = null): array

// ListSubPartitionBuilder
->addListPartition(string $name, array $values, ?string $schema = null, ?AbstractSubPartitionBuilder $subPartitions = null): self
->addListPartitions(array $values, ?string $schema = null): self
// Examples:
//   ->addListPartitions(['new', 'void', 'used'])  // auto-generated names using baseName
//   ->addListPartitions(['new' => '%_new', 'void' => '%_void'])  // % = baseName placeholder
//   ->addListPartitions(['false' => 'inactive', 'true' => 'active'])  // casts based on column type (auto-detected)

// RangeSubPartitionBuilder
// All date parameters accept: int (year), string ("2024", "2024-01", "2024-01-15"), or DateTimeInterface
->addRangePartition(string $name, mixed $from, mixed $to, ?string $schema = null, ?AbstractSubPartitionBuilder $subPartitions = null): self
->addYearlyPartitions(int $count, int|string|DateTimeInterface|null $start = null, ?string $prefix = null, ?string $schema = null, bool $fromToday = false): self
->addMonthlyPartitions(int $count, int|string|DateTimeInterface|null $start = null, ?string $prefix = null, ?string $schema = null, bool $fromToday = false): self
->addWeeklyPartitions(int $count, int|string|DateTimeInterface|null $start = null, ?string $prefix = null, ?string $schema = null, bool $fromToday = false): self
->addDailyPartitions(int $count, int|string|DateTimeInterface|null $start = null, ?string $prefix = null, ?string $schema = null, bool $fromToday = false): self
// If prefix is null, auto-generates using baseName: {baseName}_y, {baseName}_m, {baseName}_w, {baseName}_d

// HashSubPartitionBuilder
->addHashPartition(string $name, int $modulus, int $remainder, ?string $schema = null, ?AbstractSubPartitionBuilder $subPartitions = null): self
->addHashPartitions(int $modulus, ?string $prefix = null, ?string $schema = null): self
// If prefix is null, auto-generates using baseName: {baseName}_p
```

### Value Objects

[](#value-objects)

```
// RangePartition
RangePartition::range(string $name)
    ->withRange(mixed $from, mixed $to): self
    ->withSchema(string $schema): self
    ->withSubPartitions(SubPartitionBuilder $builder): self

// ListPartition
ListPartition::list(string $name)
    ->withValues(array $values): self
    ->withValue(mixed $value): self
    ->withSchema(string $schema): self

// HashPartition
HashPartition::hash(string $name)
    ->withHash(int $modulus, int $remainder): self
    ->withSchema(string $schema): self

// Sub-partition value objects (all support nested sub-partitions)
RangeSubPartition::create(string $name)
    ->withRange(mixed $from, mixed $to): self
    ->withSchema(string $schema): self
    ->withTablespace(string $tablespace): self
    ->withSubPartitions(AbstractSubPartitionBuilder $builder): self

ListSubPartition::create(string $name)
    ->withValues(array $values): self
    ->withSchema(string $schema): self
    ->withTablespace(string $tablespace): self
    ->withSubPartitions(AbstractSubPartitionBuilder $builder): self

HashSubPartition::create(string $name)
    ->withHash(int $modulus, int $remainder): self
    ->withSchema(string $schema): self
    ->withTablespace(string $tablespace): self
    ->withSubPartitions(AbstractSubPartitionBuilder $builder): self

// Common SubPartition methods
->getName(): string
->getSchema(): ?string
->getTablespace(): ?string
->hasSubPartitions(): bool
->getSubPartitions(): ?AbstractSubPartitionBuilder
->toArray(): array
```

### PartitionManager Service

[](#partitionmanager-service)

```
// Query
->getPartitions(string $table, ?string $connection = null): array
->getPartitionInfo(string $table, string $partitionName, ?string $connection = null): ?object
->isPartitioned(string $table, ?string $connection = null): bool
->getPartitionStrategy(string $table, ?string $connection = null): ?PartitionType
->getPartitionColumns(string $table, ?string $connection = null): array
->getTableSize(string $table, ?string $connection = null): string
->getPartitionCount(string $table, ?string $connection = null): int
->getOldestPartition(string $table, ?string $connection = null): ?object
->getNewestPartition(string $table, ?string $connection = null): ?object

// Maintenance
->analyzePartition(string $partitionName, ?string $connection = null): void
->vacuumPartition(string $partitionName, bool $full = false, ?string $connection = null): void
->dropOldPartitions(string $table, DateTime $before, ?string $connection = null): array
```

License
-------

[](#license)

MIT

###  Health Score

36

—

LowBetter than 82% of packages

Maintenance74

Regular maintenance activity

Popularity8

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity47

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

Total

12

Last Release

139d ago

### Community

Maintainers

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

---

Top Contributors

[![professor93](https://avatars.githubusercontent.com/u/5443574?v=4)](https://github.com/professor93 "professor93 (18 commits)")

---

Tags

laraveldatabasepostgresqlPartitiontable-partitioning

### Embed Badge

![Health badge](/badges/uzbek-laravel-partition-manager/health.svg)

```
[![Health](https://phpackages.com/badges/uzbek-laravel-partition-manager/health.svg)](https://phpackages.com/packages/uzbek-laravel-partition-manager)
```

###  Alternatives

[mongodb/laravel-mongodb

A MongoDB based Eloquent model and Query builder for Laravel

7.1k7.2M71](/packages/mongodb-laravel-mongodb)[tucker-eric/eloquentfilter

An Eloquent way to filter Eloquent Models

1.8k4.8M26](/packages/tucker-eric-eloquentfilter)[clickbar/laravel-magellan

This package provides functionality for working with the postgis extension in Laravel.

423715.4k1](/packages/clickbar-laravel-magellan)[cybercog/laravel-clickhouse

ClickHouse migrations for Laravel

163166.8k](/packages/cybercog-laravel-clickhouse)[toponepercent/baum

Baum is an implementation of the Nested Set pattern for Eloquent models.

3154.7k](/packages/toponepercent-baum)[baril/bonsai

An implementation of the Closure Tables pattern for Eloquent.

3593.5k](/packages/baril-bonsai)

PHPackages © 2026

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